Компания «Цифра» разрабатывает решения для эффективной работы промышленных предприятий. Ее клиенту, предприятию, занимающемуся добычей и очисткой золотоносной руды, необходимо оптимизировать производство, чтобы не запускать процессы с убыточными характеристиками.
Задача: Спрогнозировать коэффициент восстановления золота из руды с помощью модели машинного обучения.
Качество модели необходимо оценить по метрике sMAPE, симметричному среднему абсолютному процентному отклонению (Symmetric Mean Absolute Percentage Error).
Описание получения золота из руды
Добытая руда проходит первичную обработку, затем её отправляют на флотацию (обогащение) и двухэтапную очистку.
Этапы обработки
Параметры этапов
Возможные значения для блока [тип_параметра]:
Описание данных
Данные разделены на три датасета - исходный, обучающий и тестовый.
Имеется информация об исходном сырье и с данными после его очистки. Данные индексируются датой и временем получения информации (признак date). Показатели соседних партий обычно схожи.
Наименование признаков
[этап].[тип_параметра].[название_параметра]
Пример: rougher.input.feed_ag
Особенности:
Некоторые параметры недоступны, потому что замеряются и/или рассчитываются значительно позже. Из-за этого в тестовой выборке отсутствуют некоторые признаки, которые могут быть в обучающей. Также в тестовом наборе нет целевых признаков.
Исходный датасет содержит обучающую и тестовую выборки со всеми признаками.
#!pip install phik
# import libraries
import datetime
import os
import warnings
warnings.filterwarnings('ignore')
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from phik.report import correlation_report, plot_correlation_matrix
from sklearn.dummy import DummyRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, make_scorer
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import cross_val_score
# display settings
pd.options.display.max_columns = None
pd.set_option('display.max_colwidth', 100)
pd.set_option("display.precision", 4)
%matplotlib inline
Из описания данных известно, что признак date - дата и время получения информации, при чтении файла приведем его сразу в формат datetime.
# data path
path = os.path.join(os.path.dirname(os.getcwd()), '9_Project2')
# define function to read files and display information about the data
def read_file(dataset_type):
""" Функция принимает строку -
тип датасета (full, train, tast).
Читает данные, выводит основную информацию
по файлу, возвращает датафрейм с данными"""
# reading files
filename = 'gold_recovery_' + dataset_type + '_new.csv'
try:
df = pd.read_csv(os.path.join(path, filename),
parse_dates=['date'])
except:
df = pd.read_csv('/datasets/'+filename,
parse_dates=['date'])
# get first and last 5 rows
display(df)
# get information about the data
print()
print(df.info())
# check for duplicates
print()
if df.duplicated().sum() > 0:
print('В данных есть явные дубликаты')
else:
print('В данных нет явных дубликатов')
# check for NaN
if df.isna().sum().sum() > 0:
print('В данных есть пропущенные значения')
else:
print('В данных нет пропущенных значений')
return df
# complete data
data_full = read_file('full')
| date | final.output.concentrate_ag | final.output.concentrate_pb | final.output.concentrate_sol | final.output.concentrate_au | final.output.recovery | final.output.tail_ag | final.output.tail_pb | final.output.tail_sol | final.output.tail_au | primary_cleaner.input.sulfate | primary_cleaner.input.depressant | primary_cleaner.input.feed_size | primary_cleaner.input.xanthate | primary_cleaner.output.concentrate_ag | primary_cleaner.output.concentrate_pb | primary_cleaner.output.concentrate_sol | primary_cleaner.output.concentrate_au | primary_cleaner.output.tail_ag | primary_cleaner.output.tail_pb | primary_cleaner.output.tail_sol | primary_cleaner.output.tail_au | primary_cleaner.state.floatbank8_a_air | primary_cleaner.state.floatbank8_a_level | primary_cleaner.state.floatbank8_b_air | primary_cleaner.state.floatbank8_b_level | primary_cleaner.state.floatbank8_c_air | primary_cleaner.state.floatbank8_c_level | primary_cleaner.state.floatbank8_d_air | primary_cleaner.state.floatbank8_d_level | rougher.calculation.sulfate_to_au_concentrate | rougher.calculation.floatbank10_sulfate_to_au_feed | rougher.calculation.floatbank11_sulfate_to_au_feed | rougher.calculation.au_pb_ratio | rougher.input.feed_ag | rougher.input.feed_pb | rougher.input.feed_rate | rougher.input.feed_size | rougher.input.feed_sol | rougher.input.feed_au | rougher.input.floatbank10_sulfate | rougher.input.floatbank10_xanthate | rougher.input.floatbank11_sulfate | rougher.input.floatbank11_xanthate | rougher.output.concentrate_ag | rougher.output.concentrate_pb | rougher.output.concentrate_sol | rougher.output.concentrate_au | rougher.output.recovery | rougher.output.tail_ag | rougher.output.tail_pb | rougher.output.tail_sol | rougher.output.tail_au | rougher.state.floatbank10_a_air | rougher.state.floatbank10_a_level | rougher.state.floatbank10_b_air | rougher.state.floatbank10_b_level | rougher.state.floatbank10_c_air | rougher.state.floatbank10_c_level | rougher.state.floatbank10_d_air | rougher.state.floatbank10_d_level | rougher.state.floatbank10_e_air | rougher.state.floatbank10_e_level | rougher.state.floatbank10_f_air | rougher.state.floatbank10_f_level | secondary_cleaner.output.tail_ag | secondary_cleaner.output.tail_pb | secondary_cleaner.output.tail_sol | secondary_cleaner.output.tail_au | secondary_cleaner.state.floatbank2_a_air | secondary_cleaner.state.floatbank2_a_level | secondary_cleaner.state.floatbank2_b_air | secondary_cleaner.state.floatbank2_b_level | secondary_cleaner.state.floatbank3_a_air | secondary_cleaner.state.floatbank3_a_level | secondary_cleaner.state.floatbank3_b_air | secondary_cleaner.state.floatbank3_b_level | secondary_cleaner.state.floatbank4_a_air | secondary_cleaner.state.floatbank4_a_level | secondary_cleaner.state.floatbank4_b_air | secondary_cleaner.state.floatbank4_b_level | secondary_cleaner.state.floatbank5_a_air | secondary_cleaner.state.floatbank5_a_level | secondary_cleaner.state.floatbank5_b_air | secondary_cleaner.state.floatbank5_b_level | secondary_cleaner.state.floatbank6_a_air | secondary_cleaner.state.floatbank6_a_level | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2016-01-15 00:00:00 | 6.0554 | 9.8896 | 5.5073 | 42.1920 | 70.5412 | 10.4120 | 0.8954 | 16.9043 | 2.1431 | 127.0920 | 10.1283 | 7.25 | 0.9888 | 8.5476 | 10.3896 | 19.5293 | 34.1744 | 14.9365 | 2.5349 | 7.4761 | 2.1067 | 1549.7758 | -498.9121 | 1551.4342 | -516.4034 | 1549.8739 | -498.6666 | 1554.3674 | -493.4281 | 41885.7070 | 3481.7791 | 3520.3372 | 2.8387 | 6.1004 | 2.2849 | 523.5463 | 55.4866 | 36.8086 | 6.4861 | 11.9866 | 6.0080 | 11.8367 | 6.0058 | 11.5008 | 7.1011 | 28.0293 | 19.7938 | 87.1078 | 5.0080 | 0.5087 | 19.1543 | 1.1702 | 999.7069 | -404.0670 | 1603.0114 | -434.7150 | 1602.3750 | -442.2045 | 1598.9373 | -451.2941 | 1404.4720 | -455.4630 | 1416.3550 | -451.9396 | 14.5002 | 4.6948 | 8.7646 | 2.6062 | 25.8531 | -498.5265 | 23.8937 | -501.4063 | 23.9618 | -495.2628 | 21.9404 | -499.3410 | 14.0168 | -502.4880 | 12.0999 | -504.7159 | 9.9256 | -498.3102 | 8.0797 | -500.4710 | 14.1513 | -605.8420 |
| 1 | 2016-01-15 01:00:00 | 6.0294 | 9.9689 | 5.2578 | 42.7016 | 69.2662 | 10.4627 | 0.9275 | 16.6345 | 2.2249 | 125.6292 | 10.2963 | 7.25 | 1.0027 | 8.5587 | 10.4971 | 19.3691 | 34.1185 | 16.2505 | 3.0496 | 6.7339 | 2.3530 | 1576.1667 | -500.9050 | 1575.9506 | -499.8659 | 1575.9942 | -499.3151 | 1574.4793 | -498.9317 | 42050.8618 | 3498.3710 | 3489.9819 | 2.8590 | 6.1611 | 2.2660 | 525.2906 | 57.2787 | 35.7534 | 6.4786 | 11.9712 | 6.0058 | 11.9962 | 6.0126 | 11.6159 | 7.2788 | 28.0671 | 20.0510 | 86.8433 | 4.9554 | 0.5367 | 18.9652 | 1.1848 | 1000.2864 | -400.0652 | 1600.7546 | -449.9534 | 1600.4796 | -449.8306 | 1600.5276 | -449.9536 | 1399.2271 | -450.8698 | 1399.7195 | -450.1190 | 14.2655 | 4.5925 | 9.0015 | 2.4882 | 25.8805 | -499.9897 | 23.8895 | -500.3724 | 23.9706 | -500.0855 | 22.0857 | -499.4469 | 13.9923 | -505.5033 | 11.9505 | -501.3315 | 10.0392 | -500.1700 | 7.9848 | -500.5822 | 13.9984 | -599.7872 |
| 2 | 2016-01-15 02:00:00 | 6.0559 | 10.2140 | 5.3838 | 42.6575 | 68.1164 | 10.5070 | 0.9537 | 16.2088 | 2.2579 | 123.8198 | 11.3163 | 7.25 | 0.9913 | 8.6035 | 10.3545 | 19.1676 | 33.9695 | 16.4918 | 3.1247 | 6.4718 | 2.4168 | 1601.5562 | -499.9978 | 1600.3867 | -500.6078 | 1602.0035 | -500.8701 | 1599.5415 | -499.8274 | 42018.1012 | 3495.3489 | 3502.3598 | 2.9460 | 6.1165 | 2.1596 | 530.0266 | 57.5106 | 35.9716 | 6.3622 | 11.9206 | 6.1974 | 11.9203 | 6.2046 | 11.6958 | 7.2168 | 27.4540 | 19.7372 | 86.8423 | 4.8435 | 0.5464 | 18.8085 | 1.1626 | 999.7196 | -400.0740 | 1599.3373 | -450.0085 | 1599.6728 | -449.9545 | 1599.8493 | -449.9542 | 1399.1809 | -449.9376 | 1400.3167 | -450.5271 | 14.1157 | 4.6248 | 8.8429 | 2.4582 | 26.0052 | -499.9296 | 23.8867 | -499.9519 | 23.9135 | -499.4423 | 23.9577 | -499.9020 | 14.0150 | -502.5209 | 11.9128 | -501.1334 | 10.0709 | -500.1291 | 8.0139 | -500.5176 | 14.0287 | -601.4274 |
| 3 | 2016-01-15 03:00:00 | 6.0480 | 9.9770 | 4.8586 | 42.6898 | 68.3475 | 10.4228 | 0.8838 | 16.5328 | 2.1468 | 122.2702 | 11.3221 | 7.25 | 0.9967 | 7.2219 | 8.4966 | 15.9785 | 28.2607 | 16.0244 | 2.9604 | 6.8438 | 2.2621 | 1599.9687 | -500.9518 | 1600.6592 | -499.6771 | 1600.3041 | -500.7280 | 1600.4495 | -500.0526 | 42029.4480 | 3498.5783 | 3499.1629 | 3.0023 | 6.0433 | 2.0378 | 542.5904 | 57.7927 | 36.8622 | 6.1182 | 11.6301 | 6.2032 | 11.6924 | 6.1966 | 11.9150 | 7.1756 | 27.3413 | 19.3208 | 87.2264 | 4.6553 | 0.5425 | 19.3302 | 1.0798 | 999.8148 | -400.2002 | 1600.0594 | -450.6199 | 1600.0128 | -449.9105 | 1597.7252 | -450.1301 | 1400.9432 | -450.0301 | 1400.2347 | -449.7908 | 13.7321 | 4.4825 | 9.1229 | 2.3221 | 25.9425 | -499.1767 | 23.9555 | -499.8488 | 23.9668 | -500.0088 | 23.9544 | -499.9447 | 14.0365 | -500.8573 | 11.9996 | -501.1937 | 9.9704 | -499.2016 | 7.9773 | -500.2559 | 14.0056 | -599.9961 |
| 4 | 2016-01-15 04:00:00 | 6.1486 | 10.1425 | 4.9394 | 42.7741 | 66.9270 | 10.3603 | 0.7928 | 16.5257 | 2.0553 | 117.9882 | 11.9136 | 7.25 | 1.0099 | 9.0894 | 9.9868 | 19.1999 | 33.0449 | 16.4802 | 3.1121 | 6.5502 | 2.2771 | 1601.3397 | -498.9755 | 1601.4379 | -500.3232 | 1599.5819 | -500.8882 | 1602.6495 | -500.5930 | 42125.3542 | 3494.8008 | 3506.6793 | 3.1696 | 6.0609 | 1.7869 | 540.5319 | 56.0472 | 34.3477 | 5.6637 | 10.9578 | 6.1988 | 10.9605 | 6.1949 | 12.4111 | 7.2402 | 27.0410 | 19.2161 | 86.6888 | 4.5528 | 0.5154 | 19.2674 | 1.0126 | 999.6787 | -399.7527 | 1600.2088 | -449.5996 | 1600.3577 | -450.0344 | 1599.7590 | -449.9098 | 1401.5609 | -448.8772 | 1401.1602 | -450.4071 | 14.0800 | 4.4707 | 8.8710 | 2.3304 | 26.0248 | -500.2791 | 23.9553 | -500.5936 | 23.9857 | -500.0838 | 23.9589 | -499.9903 | 14.0273 | -499.8386 | 11.9531 | -501.0539 | 9.9257 | -501.6867 | 7.8942 | -500.3560 | 13.9966 | -601.4967 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 19434 | 2018-08-18 06:59:59 | 3.2249 | 11.3562 | 6.8035 | 46.7140 | 73.7551 | 8.7696 | 3.1415 | 10.4032 | 1.5292 | 123.3818 | 8.0289 | 6.50 | 1.3042 | 6.5592 | 12.4460 | 7.0563 | 32.9402 | 22.8546 | 6.5315 | 3.9343 | 2.3144 | 1648.4212 | -400.3822 | 1648.7420 | -400.3597 | 1648.5782 | -399.3636 | 1648.8340 | -399.6692 | 45912.9426 | 2497.6530 | 2499.1780 | 1.1556 | 6.0919 | 4.6176 | 560.8891 | 85.7183 | 37.3698 | 5.3359 | 7.7628 | 9.1586 | 7.7667 | 9.1561 | 11.1249 | 10.9840 | 30.0689 | 18.6036 | 89.5744 | 4.2073 | 0.6129 | 16.6666 | 0.7486 | 1199.2459 | -300.8455 | 1149.8079 | -498.7897 | 1047.9636 | -498.4131 | 946.6410 | -499.1525 | 849.6649 | -499.2145 | 849.7581 | -497.4487 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 35.0432 | -499.0457 | 29.9067 | -499.9799 | 26.0024 | -499.9534 | 22.9872 | -499.9674 | 23.0315 | -501.1679 | 20.0076 | -499.7400 | 18.0060 | -499.8344 | 13.0011 | -500.1557 | 20.0078 | -501.2964 |
| 19435 | 2018-08-18 07:59:59 | 3.1960 | 11.3494 | 6.8622 | 46.8668 | 69.0493 | 8.8973 | 3.1305 | 10.5495 | 1.6125 | 120.8782 | 7.9626 | 6.50 | 1.3024 | 6.6124 | 12.6239 | 7.5423 | 32.9253 | 23.0025 | 6.6297 | 4.0891 | 2.4629 | 1649.8202 | -399.9310 | 1649.3575 | -399.7212 | 1648.6562 | -401.1958 | 1649.7251 | -400.6363 | 46200.0996 | 2614.4039 | 2518.5501 | 1.1673 | 6.1213 | 4.1450 | 559.0318 | 119.4992 | 38.5916 | 4.8386 | 7.3567 | 9.3050 | 7.0955 | 9.2979 | 11.4260 | 10.8882 | 29.7840 | 18.4414 | 87.7240 | 4.1779 | 0.6506 | 16.9606 | 0.7716 | 1196.5693 | -299.5122 | 1147.6752 | -500.6083 | 1048.5657 | -500.9328 | 949.7736 | -500.0231 | 848.5152 | -500.2894 | 850.0131 | -496.8221 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 35.0261 | -499.8919 | 29.9218 | -499.9497 | 26.0317 | -500.3846 | 22.9911 | -500.0796 | 22.9601 | -501.6128 | 20.0357 | -500.2514 | 17.9985 | -500.3952 | 12.9540 | -499.8952 | 19.9685 | -501.0416 |
| 19436 | 2018-08-18 08:59:59 | 3.1100 | 11.4344 | 6.8860 | 46.7957 | 67.0022 | 8.5296 | 2.9114 | 11.1151 | 1.5966 | 105.6661 | 7.9551 | 6.50 | 1.3159 | 7.1289 | 12.6336 | 7.9419 | 31.8567 | 22.2981 | 6.2783 | 4.4575 | 2.6122 | 1649.1668 | -399.8886 | 1649.1969 | -399.6776 | 1647.8970 | -399.9883 | 1649.7727 | -399.8319 | 44585.1813 | 2510.8135 | 2510.1424 | 1.1256 | 5.9705 | 4.0200 | 555.6829 | 122.2627 | 40.0740 | 4.5251 | 6.5860 | 9.2996 | 6.5841 | 9.3001 | 8.5235 | 8.9551 | 22.7865 | 15.1112 | 88.8906 | 4.0500 | 0.6361 | 18.3231 | 0.6851 | 1204.8666 | -299.2357 | 1149.9429 | -501.7179 | 1049.6044 | -500.5491 | 952.7027 | -502.3523 | 849.0160 | -500.5057 | 850.4556 | -506.8980 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 35.0036 | -501.0838 | 29.9905 | -611.8559 | 25.9484 | -500.0673 | 22.9683 | -499.8394 | 23.0157 | -501.7116 | 19.9512 | -499.8570 | 18.0195 | -500.4512 | 13.0234 | -499.9144 | 19.9909 | -501.5185 |
| 19437 | 2018-08-18 09:59:59 | 3.3672 | 11.6256 | 6.7994 | 46.4082 | 65.5232 | 8.7772 | 2.8192 | 10.4638 | 1.6029 | 98.8805 | 7.9842 | 6.50 | 1.2420 | 7.4904 | 12.0124 | 6.9430 | 30.7709 | 22.7147 | 6.2531 | 3.5571 | 2.8006 | 1646.5478 | -398.9771 | 1648.2122 | -400.3833 | 1648.9174 | -399.5213 | 1651.4986 | -399.7453 | 44084.7357 | 2507.5725 | 2507.7234 | 1.1179 | 6.0481 | 3.9025 | 544.7317 | 123.7424 | 39.7139 | 4.3628 | 6.2101 | 9.2977 | 6.2095 | 9.2972 | 11.6588 | 10.6554 | 29.0527 | 17.8348 | 89.8581 | 3.9025 | 0.6256 | 19.4237 | 0.5671 | 1201.9042 | -299.9073 | 1154.0878 | -500.0366 | 1054.0098 | -500.2373 | 944.1388 | -496.8670 | 851.5898 | -499.0405 | 851.3456 | -499.1226 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 34.9807 | -498.1310 | 29.9685 | -586.0133 | 25.9717 | -499.6084 | 22.9584 | -499.8213 | 23.0250 | -501.1534 | 20.0541 | -500.3147 | 17.9795 | -499.2729 | 12.9924 | -499.9763 | 20.0140 | -500.6255 |
| 19438 | 2018-08-18 10:59:59 | 3.5984 | 11.7378 | 6.7175 | 46.2994 | 70.2815 | 8.4067 | 2.5175 | 10.6522 | 1.3894 | 95.2484 | 8.0790 | 6.50 | 1.2830 | 7.5376 | 11.6503 | 6.2036 | 30.3566 | 22.7359 | 6.0843 | 3.0267 | 2.7080 | 1648.7599 | -399.8621 | 1650.1354 | -399.9573 | 1648.8319 | -400.5861 | 1649.4646 | -400.6733 | 44082.8666 | 2487.4778 | 2488.6261 | 1.1264 | 6.1587 | 3.8757 | 555.8202 | 94.5444 | 39.1351 | 4.3655 | 6.1470 | 9.3086 | 6.1689 | 9.3099 | 11.9595 | 10.7021 | 29.0782 | 17.8041 | 89.5150 | 3.9255 | 0.6387 | 19.9467 | 0.5864 | 1196.2381 | -299.8627 | 1147.2482 | -500.3632 | 1047.2791 | -500.3541 | 948.7566 | -498.4394 | 849.4419 | -499.2555 | 850.1122 | -499.4071 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 34.9409 | -500.1505 | 30.0319 | -500.3283 | 26.0340 | -500.1478 | 22.9523 | -500.0377 | 23.0186 | -500.4927 | 20.0202 | -500.2203 | 17.9635 | -499.9395 | 12.9903 | -500.0810 | 19.9903 | -499.1916 |
19439 rows × 87 columns
<class 'pandas.core.frame.DataFrame'> RangeIndex: 19439 entries, 0 to 19438 Data columns (total 87 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 date 19439 non-null datetime64[ns] 1 final.output.concentrate_ag 19438 non-null float64 2 final.output.concentrate_pb 19438 non-null float64 3 final.output.concentrate_sol 19228 non-null float64 4 final.output.concentrate_au 19439 non-null float64 5 final.output.recovery 19439 non-null float64 6 final.output.tail_ag 19438 non-null float64 7 final.output.tail_pb 19338 non-null float64 8 final.output.tail_sol 19433 non-null float64 9 final.output.tail_au 19439 non-null float64 10 primary_cleaner.input.sulfate 19415 non-null float64 11 primary_cleaner.input.depressant 19402 non-null float64 12 primary_cleaner.input.feed_size 19439 non-null float64 13 primary_cleaner.input.xanthate 19335 non-null float64 14 primary_cleaner.output.concentrate_ag 19439 non-null float64 15 primary_cleaner.output.concentrate_pb 19323 non-null float64 16 primary_cleaner.output.concentrate_sol 19069 non-null float64 17 primary_cleaner.output.concentrate_au 19439 non-null float64 18 primary_cleaner.output.tail_ag 19435 non-null float64 19 primary_cleaner.output.tail_pb 19418 non-null float64 20 primary_cleaner.output.tail_sol 19377 non-null float64 21 primary_cleaner.output.tail_au 19439 non-null float64 22 primary_cleaner.state.floatbank8_a_air 19435 non-null float64 23 primary_cleaner.state.floatbank8_a_level 19438 non-null float64 24 primary_cleaner.state.floatbank8_b_air 19435 non-null float64 25 primary_cleaner.state.floatbank8_b_level 19438 non-null float64 26 primary_cleaner.state.floatbank8_c_air 19437 non-null float64 27 primary_cleaner.state.floatbank8_c_level 19438 non-null float64 28 primary_cleaner.state.floatbank8_d_air 19436 non-null float64 29 primary_cleaner.state.floatbank8_d_level 19438 non-null float64 30 rougher.calculation.sulfate_to_au_concentrate 19437 non-null float64 31 rougher.calculation.floatbank10_sulfate_to_au_feed 19437 non-null float64 32 rougher.calculation.floatbank11_sulfate_to_au_feed 19437 non-null float64 33 rougher.calculation.au_pb_ratio 19439 non-null float64 34 rougher.input.feed_ag 19439 non-null float64 35 rougher.input.feed_pb 19339 non-null float64 36 rougher.input.feed_rate 19428 non-null float64 37 rougher.input.feed_size 19294 non-null float64 38 rougher.input.feed_sol 19340 non-null float64 39 rougher.input.feed_au 19439 non-null float64 40 rougher.input.floatbank10_sulfate 19405 non-null float64 41 rougher.input.floatbank10_xanthate 19431 non-null float64 42 rougher.input.floatbank11_sulfate 19395 non-null float64 43 rougher.input.floatbank11_xanthate 18986 non-null float64 44 rougher.output.concentrate_ag 19439 non-null float64 45 rougher.output.concentrate_pb 19439 non-null float64 46 rougher.output.concentrate_sol 19416 non-null float64 47 rougher.output.concentrate_au 19439 non-null float64 48 rougher.output.recovery 19439 non-null float64 49 rougher.output.tail_ag 19438 non-null float64 50 rougher.output.tail_pb 19439 non-null float64 51 rougher.output.tail_sol 19439 non-null float64 52 rougher.output.tail_au 19439 non-null float64 53 rougher.state.floatbank10_a_air 19438 non-null float64 54 rougher.state.floatbank10_a_level 19438 non-null float64 55 rougher.state.floatbank10_b_air 19438 non-null float64 56 rougher.state.floatbank10_b_level 19438 non-null float64 57 rougher.state.floatbank10_c_air 19438 non-null float64 58 rougher.state.floatbank10_c_level 19438 non-null float64 59 rougher.state.floatbank10_d_air 19439 non-null float64 60 rougher.state.floatbank10_d_level 19439 non-null float64 61 rougher.state.floatbank10_e_air 19003 non-null float64 62 rougher.state.floatbank10_e_level 19439 non-null float64 63 rougher.state.floatbank10_f_air 19439 non-null float64 64 rougher.state.floatbank10_f_level 19439 non-null float64 65 secondary_cleaner.output.tail_ag 19437 non-null float64 66 secondary_cleaner.output.tail_pb 19427 non-null float64 67 secondary_cleaner.output.tail_sol 17691 non-null float64 68 secondary_cleaner.output.tail_au 19439 non-null float64 69 secondary_cleaner.state.floatbank2_a_air 19219 non-null float64 70 secondary_cleaner.state.floatbank2_a_level 19438 non-null float64 71 secondary_cleaner.state.floatbank2_b_air 19416 non-null float64 72 secondary_cleaner.state.floatbank2_b_level 19438 non-null float64 73 secondary_cleaner.state.floatbank3_a_air 19426 non-null float64 74 secondary_cleaner.state.floatbank3_a_level 19438 non-null float64 75 secondary_cleaner.state.floatbank3_b_air 19438 non-null float64 76 secondary_cleaner.state.floatbank3_b_level 19438 non-null float64 77 secondary_cleaner.state.floatbank4_a_air 19433 non-null float64 78 secondary_cleaner.state.floatbank4_a_level 19438 non-null float64 79 secondary_cleaner.state.floatbank4_b_air 19438 non-null float64 80 secondary_cleaner.state.floatbank4_b_level 19438 non-null float64 81 secondary_cleaner.state.floatbank5_a_air 19438 non-null float64 82 secondary_cleaner.state.floatbank5_a_level 19438 non-null float64 83 secondary_cleaner.state.floatbank5_b_air 19438 non-null float64 84 secondary_cleaner.state.floatbank5_b_level 19438 non-null float64 85 secondary_cleaner.state.floatbank6_a_air 19437 non-null float64 86 secondary_cleaner.state.floatbank6_a_level 19438 non-null float64 dtypes: datetime64[ns](1), float64(86) memory usage: 12.9 MB None В данных нет явных дубликатов В данных есть пропущенные значения
# train data
data_train = read_file('train')
| date | final.output.concentrate_ag | final.output.concentrate_pb | final.output.concentrate_sol | final.output.concentrate_au | final.output.recovery | final.output.tail_ag | final.output.tail_pb | final.output.tail_sol | final.output.tail_au | primary_cleaner.input.sulfate | primary_cleaner.input.depressant | primary_cleaner.input.feed_size | primary_cleaner.input.xanthate | primary_cleaner.output.concentrate_ag | primary_cleaner.output.concentrate_pb | primary_cleaner.output.concentrate_sol | primary_cleaner.output.concentrate_au | primary_cleaner.output.tail_ag | primary_cleaner.output.tail_pb | primary_cleaner.output.tail_sol | primary_cleaner.output.tail_au | primary_cleaner.state.floatbank8_a_air | primary_cleaner.state.floatbank8_a_level | primary_cleaner.state.floatbank8_b_air | primary_cleaner.state.floatbank8_b_level | primary_cleaner.state.floatbank8_c_air | primary_cleaner.state.floatbank8_c_level | primary_cleaner.state.floatbank8_d_air | primary_cleaner.state.floatbank8_d_level | rougher.calculation.sulfate_to_au_concentrate | rougher.calculation.floatbank10_sulfate_to_au_feed | rougher.calculation.floatbank11_sulfate_to_au_feed | rougher.calculation.au_pb_ratio | rougher.input.feed_ag | rougher.input.feed_pb | rougher.input.feed_rate | rougher.input.feed_size | rougher.input.feed_sol | rougher.input.feed_au | rougher.input.floatbank10_sulfate | rougher.input.floatbank10_xanthate | rougher.input.floatbank11_sulfate | rougher.input.floatbank11_xanthate | rougher.output.concentrate_ag | rougher.output.concentrate_pb | rougher.output.concentrate_sol | rougher.output.concentrate_au | rougher.output.recovery | rougher.output.tail_ag | rougher.output.tail_pb | rougher.output.tail_sol | rougher.output.tail_au | rougher.state.floatbank10_a_air | rougher.state.floatbank10_a_level | rougher.state.floatbank10_b_air | rougher.state.floatbank10_b_level | rougher.state.floatbank10_c_air | rougher.state.floatbank10_c_level | rougher.state.floatbank10_d_air | rougher.state.floatbank10_d_level | rougher.state.floatbank10_e_air | rougher.state.floatbank10_e_level | rougher.state.floatbank10_f_air | rougher.state.floatbank10_f_level | secondary_cleaner.output.tail_ag | secondary_cleaner.output.tail_pb | secondary_cleaner.output.tail_sol | secondary_cleaner.output.tail_au | secondary_cleaner.state.floatbank2_a_air | secondary_cleaner.state.floatbank2_a_level | secondary_cleaner.state.floatbank2_b_air | secondary_cleaner.state.floatbank2_b_level | secondary_cleaner.state.floatbank3_a_air | secondary_cleaner.state.floatbank3_a_level | secondary_cleaner.state.floatbank3_b_air | secondary_cleaner.state.floatbank3_b_level | secondary_cleaner.state.floatbank4_a_air | secondary_cleaner.state.floatbank4_a_level | secondary_cleaner.state.floatbank4_b_air | secondary_cleaner.state.floatbank4_b_level | secondary_cleaner.state.floatbank5_a_air | secondary_cleaner.state.floatbank5_a_level | secondary_cleaner.state.floatbank5_b_air | secondary_cleaner.state.floatbank5_b_level | secondary_cleaner.state.floatbank6_a_air | secondary_cleaner.state.floatbank6_a_level | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2016-01-15 00:00:00 | 6.0554 | 9.8896 | 5.5073 | 42.1920 | 70.5412 | 10.4120 | 0.8954 | 16.9043 | 2.1431 | 127.0920 | 10.1283 | 7.25 | 0.9888 | 8.5476 | 10.3896 | 19.5293 | 34.1744 | 14.9365 | 2.5349 | 7.4761 | 2.1067 | 1549.7758 | -498.9121 | 1551.4342 | -516.4034 | 1549.8739 | -498.6666 | 1554.3674 | -493.4281 | 41885.7070 | 3481.7791 | 3520.3372 | 2.8387 | 6.1004 | 2.2849 | 523.5463 | 55.4866 | 36.8086 | 6.4861 | 11.9866 | 6.0080 | 11.8367 | 6.0058 | 11.5008 | 7.1011 | 28.0293 | 19.7938 | 87.1078 | 5.0080 | 0.5087 | 19.1543 | 1.1702 | 999.7069 | -404.0670 | 1603.0114 | -434.7150 | 1602.3750 | -442.2045 | 1598.9373 | -451.2941 | 1404.4720 | -455.4630 | 1416.3550 | -451.9396 | 14.5002 | 4.6948 | 8.7646 | 2.6062 | 25.8531 | -498.5265 | 23.8937 | -501.4063 | 23.9618 | -495.2628 | 21.9404 | -499.3410 | 14.0168 | -502.4880 | 12.0999 | -504.7159 | 9.9256 | -498.3102 | 8.0797 | -500.4710 | 14.1513 | -605.8420 |
| 1 | 2016-01-15 01:00:00 | 6.0294 | 9.9689 | 5.2578 | 42.7016 | 69.2662 | 10.4627 | 0.9275 | 16.6345 | 2.2249 | 125.6292 | 10.2963 | 7.25 | 1.0027 | 8.5587 | 10.4971 | 19.3691 | 34.1185 | 16.2505 | 3.0496 | 6.7339 | 2.3530 | 1576.1667 | -500.9050 | 1575.9506 | -499.8659 | 1575.9942 | -499.3151 | 1574.4793 | -498.9317 | 42050.8618 | 3498.3710 | 3489.9819 | 2.8590 | 6.1611 | 2.2660 | 525.2906 | 57.2787 | 35.7534 | 6.4786 | 11.9712 | 6.0058 | 11.9962 | 6.0126 | 11.6159 | 7.2788 | 28.0671 | 20.0510 | 86.8433 | 4.9554 | 0.5367 | 18.9652 | 1.1848 | 1000.2864 | -400.0652 | 1600.7546 | -449.9534 | 1600.4796 | -449.8306 | 1600.5276 | -449.9536 | 1399.2271 | -450.8698 | 1399.7195 | -450.1190 | 14.2655 | 4.5925 | 9.0015 | 2.4882 | 25.8805 | -499.9897 | 23.8895 | -500.3724 | 23.9706 | -500.0855 | 22.0857 | -499.4469 | 13.9923 | -505.5033 | 11.9505 | -501.3315 | 10.0392 | -500.1700 | 7.9848 | -500.5822 | 13.9984 | -599.7872 |
| 2 | 2016-01-15 02:00:00 | 6.0559 | 10.2140 | 5.3838 | 42.6575 | 68.1164 | 10.5070 | 0.9537 | 16.2088 | 2.2579 | 123.8198 | 11.3163 | 7.25 | 0.9913 | 8.6035 | 10.3545 | 19.1676 | 33.9695 | 16.4918 | 3.1247 | 6.4718 | 2.4168 | 1601.5562 | -499.9978 | 1600.3867 | -500.6078 | 1602.0035 | -500.8701 | 1599.5415 | -499.8274 | 42018.1012 | 3495.3489 | 3502.3598 | 2.9460 | 6.1165 | 2.1596 | 530.0266 | 57.5106 | 35.9716 | 6.3622 | 11.9206 | 6.1974 | 11.9203 | 6.2046 | 11.6958 | 7.2168 | 27.4540 | 19.7372 | 86.8423 | 4.8435 | 0.5464 | 18.8085 | 1.1626 | 999.7196 | -400.0740 | 1599.3373 | -450.0085 | 1599.6728 | -449.9545 | 1599.8493 | -449.9542 | 1399.1809 | -449.9376 | 1400.3167 | -450.5271 | 14.1157 | 4.6248 | 8.8429 | 2.4582 | 26.0052 | -499.9296 | 23.8867 | -499.9519 | 23.9135 | -499.4423 | 23.9577 | -499.9020 | 14.0150 | -502.5209 | 11.9128 | -501.1334 | 10.0709 | -500.1291 | 8.0139 | -500.5176 | 14.0287 | -601.4274 |
| 3 | 2016-01-15 03:00:00 | 6.0480 | 9.9770 | 4.8586 | 42.6898 | 68.3475 | 10.4228 | 0.8838 | 16.5328 | 2.1468 | 122.2702 | 11.3221 | 7.25 | 0.9967 | 7.2219 | 8.4966 | 15.9785 | 28.2607 | 16.0244 | 2.9604 | 6.8438 | 2.2621 | 1599.9687 | -500.9518 | 1600.6592 | -499.6771 | 1600.3041 | -500.7280 | 1600.4495 | -500.0526 | 42029.4480 | 3498.5783 | 3499.1629 | 3.0023 | 6.0433 | 2.0378 | 542.5904 | 57.7927 | 36.8622 | 6.1182 | 11.6301 | 6.2032 | 11.6924 | 6.1966 | 11.9150 | 7.1756 | 27.3413 | 19.3208 | 87.2264 | 4.6553 | 0.5425 | 19.3302 | 1.0798 | 999.8148 | -400.2002 | 1600.0594 | -450.6199 | 1600.0128 | -449.9105 | 1597.7252 | -450.1301 | 1400.9432 | -450.0301 | 1400.2347 | -449.7908 | 13.7321 | 4.4825 | 9.1229 | 2.3221 | 25.9425 | -499.1767 | 23.9555 | -499.8488 | 23.9668 | -500.0088 | 23.9544 | -499.9447 | 14.0365 | -500.8573 | 11.9996 | -501.1937 | 9.9704 | -499.2016 | 7.9773 | -500.2559 | 14.0056 | -599.9961 |
| 4 | 2016-01-15 04:00:00 | 6.1486 | 10.1425 | 4.9394 | 42.7741 | 66.9270 | 10.3603 | 0.7928 | 16.5257 | 2.0553 | 117.9882 | 11.9136 | 7.25 | 1.0099 | 9.0894 | 9.9868 | 19.1999 | 33.0449 | 16.4802 | 3.1121 | 6.5502 | 2.2771 | 1601.3397 | -498.9755 | 1601.4379 | -500.3232 | 1599.5819 | -500.8882 | 1602.6495 | -500.5930 | 42125.3542 | 3494.8008 | 3506.6793 | 3.1696 | 6.0609 | 1.7869 | 540.5319 | 56.0472 | 34.3477 | 5.6637 | 10.9578 | 6.1988 | 10.9605 | 6.1949 | 12.4111 | 7.2402 | 27.0410 | 19.2161 | 86.6888 | 4.5528 | 0.5154 | 19.2674 | 1.0126 | 999.6787 | -399.7527 | 1600.2088 | -449.5996 | 1600.3577 | -450.0344 | 1599.7590 | -449.9098 | 1401.5609 | -448.8772 | 1401.1602 | -450.4071 | 14.0800 | 4.4707 | 8.8710 | 2.3304 | 26.0248 | -500.2791 | 23.9553 | -500.5936 | 23.9857 | -500.0838 | 23.9589 | -499.9903 | 14.0273 | -499.8386 | 11.9531 | -501.0539 | 9.9257 | -501.6867 | 7.8942 | -500.3560 | 13.9966 | -601.4967 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 14144 | 2018-08-18 06:59:59 | 3.2249 | 11.3562 | 6.8035 | 46.7140 | 73.7551 | 8.7696 | 3.1415 | 10.4032 | 1.5292 | 123.3818 | 8.0289 | 6.50 | 1.3042 | 6.5592 | 12.4460 | 7.0563 | 32.9402 | 22.8546 | 6.5315 | 3.9343 | 2.3144 | 1648.4212 | -400.3822 | 1648.7420 | -400.3597 | 1648.5782 | -399.3636 | 1648.8340 | -399.6692 | 45912.9426 | 2497.6530 | 2499.1780 | 1.1556 | 6.0919 | 4.6176 | 560.8891 | 85.7183 | 37.3698 | 5.3359 | 7.7628 | 9.1586 | 7.7667 | 9.1561 | 11.1249 | 10.9840 | 30.0689 | 18.6036 | 89.5744 | 4.2073 | 0.6129 | 16.6666 | 0.7486 | 1199.2459 | -300.8455 | 1149.8079 | -498.7897 | 1047.9636 | -498.4131 | 946.6410 | -499.1525 | 849.6649 | -499.2145 | 849.7581 | -497.4487 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 35.0432 | -499.0457 | 29.9067 | -499.9799 | 26.0024 | -499.9534 | 22.9872 | -499.9674 | 23.0315 | -501.1679 | 20.0076 | -499.7400 | 18.0060 | -499.8344 | 13.0011 | -500.1557 | 20.0078 | -501.2964 |
| 14145 | 2018-08-18 07:59:59 | 3.1960 | 11.3494 | 6.8622 | 46.8668 | 69.0493 | 8.8973 | 3.1305 | 10.5495 | 1.6125 | 120.8782 | 7.9626 | 6.50 | 1.3024 | 6.6124 | 12.6239 | 7.5423 | 32.9253 | 23.0025 | 6.6297 | 4.0891 | 2.4629 | 1649.8202 | -399.9310 | 1649.3575 | -399.7212 | 1648.6562 | -401.1958 | 1649.7251 | -400.6363 | 46200.0996 | 2614.4039 | 2518.5501 | 1.1673 | 6.1213 | 4.1450 | 559.0318 | 119.4992 | 38.5916 | 4.8386 | 7.3567 | 9.3050 | 7.0955 | 9.2979 | 11.4260 | 10.8882 | 29.7840 | 18.4414 | 87.7240 | 4.1779 | 0.6506 | 16.9606 | 0.7716 | 1196.5693 | -299.5122 | 1147.6752 | -500.6083 | 1048.5657 | -500.9328 | 949.7736 | -500.0231 | 848.5152 | -500.2894 | 850.0131 | -496.8221 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 35.0261 | -499.8919 | 29.9218 | -499.9497 | 26.0317 | -500.3846 | 22.9911 | -500.0796 | 22.9601 | -501.6128 | 20.0357 | -500.2514 | 17.9985 | -500.3952 | 12.9540 | -499.8952 | 19.9685 | -501.0416 |
| 14146 | 2018-08-18 08:59:59 | 3.1100 | 11.4344 | 6.8860 | 46.7957 | 67.0022 | 8.5296 | 2.9114 | 11.1151 | 1.5966 | 105.6661 | 7.9551 | 6.50 | 1.3159 | 7.1289 | 12.6336 | 7.9419 | 31.8567 | 22.2981 | 6.2783 | 4.4575 | 2.6122 | 1649.1668 | -399.8886 | 1649.1969 | -399.6776 | 1647.8970 | -399.9883 | 1649.7727 | -399.8319 | 44585.1813 | 2510.8135 | 2510.1424 | 1.1256 | 5.9705 | 4.0200 | 555.6829 | 122.2627 | 40.0740 | 4.5251 | 6.5860 | 9.2996 | 6.5841 | 9.3001 | 8.5235 | 8.9551 | 22.7865 | 15.1112 | 88.8906 | 4.0500 | 0.6361 | 18.3231 | 0.6851 | 1204.8666 | -299.2357 | 1149.9429 | -501.7179 | 1049.6044 | -500.5491 | 952.7027 | -502.3523 | 849.0160 | -500.5057 | 850.4556 | -506.8980 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 35.0036 | -501.0838 | 29.9905 | -611.8559 | 25.9484 | -500.0673 | 22.9683 | -499.8394 | 23.0157 | -501.7116 | 19.9512 | -499.8570 | 18.0195 | -500.4512 | 13.0234 | -499.9144 | 19.9909 | -501.5185 |
| 14147 | 2018-08-18 09:59:59 | 3.3672 | 11.6256 | 6.7994 | 46.4082 | 65.5232 | 8.7772 | 2.8192 | 10.4638 | 1.6029 | 98.8805 | 7.9842 | 6.50 | 1.2420 | 7.4904 | 12.0124 | 6.9430 | 30.7709 | 22.7147 | 6.2531 | 3.5571 | 2.8006 | 1646.5478 | -398.9771 | 1648.2122 | -400.3833 | 1648.9174 | -399.5213 | 1651.4986 | -399.7453 | 44084.7357 | 2507.5725 | 2507.7234 | 1.1179 | 6.0481 | 3.9025 | 544.7317 | 123.7424 | 39.7139 | 4.3628 | 6.2101 | 9.2977 | 6.2095 | 9.2972 | 11.6588 | 10.6554 | 29.0527 | 17.8348 | 89.8581 | 3.9025 | 0.6256 | 19.4237 | 0.5671 | 1201.9042 | -299.9073 | 1154.0878 | -500.0366 | 1054.0098 | -500.2373 | 944.1388 | -496.8670 | 851.5898 | -499.0405 | 851.3456 | -499.1226 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 34.9807 | -498.1310 | 29.9685 | -586.0133 | 25.9717 | -499.6084 | 22.9584 | -499.8213 | 23.0250 | -501.1534 | 20.0541 | -500.3147 | 17.9795 | -499.2729 | 12.9924 | -499.9763 | 20.0140 | -500.6255 |
| 14148 | 2018-08-18 10:59:59 | 3.5984 | 11.7378 | 6.7175 | 46.2994 | 70.2815 | 8.4067 | 2.5175 | 10.6522 | 1.3894 | 95.2484 | 8.0790 | 6.50 | 1.2830 | 7.5376 | 11.6503 | 6.2036 | 30.3566 | 22.7359 | 6.0843 | 3.0267 | 2.7080 | 1648.7599 | -399.8621 | 1650.1354 | -399.9573 | 1648.8319 | -400.5861 | 1649.4646 | -400.6733 | 44082.8666 | 2487.4778 | 2488.6261 | 1.1264 | 6.1587 | 3.8757 | 555.8202 | 94.5444 | 39.1351 | 4.3655 | 6.1470 | 9.3086 | 6.1689 | 9.3099 | 11.9595 | 10.7021 | 29.0782 | 17.8041 | 89.5150 | 3.9255 | 0.6387 | 19.9467 | 0.5864 | 1196.2381 | -299.8627 | 1147.2482 | -500.3632 | 1047.2791 | -500.3541 | 948.7566 | -498.4394 | 849.4419 | -499.2555 | 850.1122 | -499.4071 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 34.9409 | -500.1505 | 30.0319 | -500.3283 | 26.0340 | -500.1478 | 22.9523 | -500.0377 | 23.0186 | -500.4927 | 20.0202 | -500.2203 | 17.9635 | -499.9395 | 12.9903 | -500.0810 | 19.9903 | -499.1916 |
14149 rows × 87 columns
<class 'pandas.core.frame.DataFrame'> RangeIndex: 14149 entries, 0 to 14148 Data columns (total 87 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 date 14149 non-null datetime64[ns] 1 final.output.concentrate_ag 14148 non-null float64 2 final.output.concentrate_pb 14148 non-null float64 3 final.output.concentrate_sol 13938 non-null float64 4 final.output.concentrate_au 14149 non-null float64 5 final.output.recovery 14149 non-null float64 6 final.output.tail_ag 14149 non-null float64 7 final.output.tail_pb 14049 non-null float64 8 final.output.tail_sol 14144 non-null float64 9 final.output.tail_au 14149 non-null float64 10 primary_cleaner.input.sulfate 14129 non-null float64 11 primary_cleaner.input.depressant 14117 non-null float64 12 primary_cleaner.input.feed_size 14149 non-null float64 13 primary_cleaner.input.xanthate 14049 non-null float64 14 primary_cleaner.output.concentrate_ag 14149 non-null float64 15 primary_cleaner.output.concentrate_pb 14063 non-null float64 16 primary_cleaner.output.concentrate_sol 13863 non-null float64 17 primary_cleaner.output.concentrate_au 14149 non-null float64 18 primary_cleaner.output.tail_ag 14148 non-null float64 19 primary_cleaner.output.tail_pb 14134 non-null float64 20 primary_cleaner.output.tail_sol 14103 non-null float64 21 primary_cleaner.output.tail_au 14149 non-null float64 22 primary_cleaner.state.floatbank8_a_air 14145 non-null float64 23 primary_cleaner.state.floatbank8_a_level 14148 non-null float64 24 primary_cleaner.state.floatbank8_b_air 14145 non-null float64 25 primary_cleaner.state.floatbank8_b_level 14148 non-null float64 26 primary_cleaner.state.floatbank8_c_air 14147 non-null float64 27 primary_cleaner.state.floatbank8_c_level 14148 non-null float64 28 primary_cleaner.state.floatbank8_d_air 14146 non-null float64 29 primary_cleaner.state.floatbank8_d_level 14148 non-null float64 30 rougher.calculation.sulfate_to_au_concentrate 14148 non-null float64 31 rougher.calculation.floatbank10_sulfate_to_au_feed 14148 non-null float64 32 rougher.calculation.floatbank11_sulfate_to_au_feed 14148 non-null float64 33 rougher.calculation.au_pb_ratio 14149 non-null float64 34 rougher.input.feed_ag 14149 non-null float64 35 rougher.input.feed_pb 14049 non-null float64 36 rougher.input.feed_rate 14141 non-null float64 37 rougher.input.feed_size 14005 non-null float64 38 rougher.input.feed_sol 14071 non-null float64 39 rougher.input.feed_au 14149 non-null float64 40 rougher.input.floatbank10_sulfate 14120 non-null float64 41 rougher.input.floatbank10_xanthate 14141 non-null float64 42 rougher.input.floatbank11_sulfate 14113 non-null float64 43 rougher.input.floatbank11_xanthate 13721 non-null float64 44 rougher.output.concentrate_ag 14149 non-null float64 45 rougher.output.concentrate_pb 14149 non-null float64 46 rougher.output.concentrate_sol 14127 non-null float64 47 rougher.output.concentrate_au 14149 non-null float64 48 rougher.output.recovery 14149 non-null float64 49 rougher.output.tail_ag 14148 non-null float64 50 rougher.output.tail_pb 14149 non-null float64 51 rougher.output.tail_sol 14149 non-null float64 52 rougher.output.tail_au 14149 non-null float64 53 rougher.state.floatbank10_a_air 14148 non-null float64 54 rougher.state.floatbank10_a_level 14148 non-null float64 55 rougher.state.floatbank10_b_air 14148 non-null float64 56 rougher.state.floatbank10_b_level 14148 non-null float64 57 rougher.state.floatbank10_c_air 14148 non-null float64 58 rougher.state.floatbank10_c_level 14148 non-null float64 59 rougher.state.floatbank10_d_air 14149 non-null float64 60 rougher.state.floatbank10_d_level 14149 non-null float64 61 rougher.state.floatbank10_e_air 13713 non-null float64 62 rougher.state.floatbank10_e_level 14149 non-null float64 63 rougher.state.floatbank10_f_air 14149 non-null float64 64 rougher.state.floatbank10_f_level 14149 non-null float64 65 secondary_cleaner.output.tail_ag 14147 non-null float64 66 secondary_cleaner.output.tail_pb 14139 non-null float64 67 secondary_cleaner.output.tail_sol 12544 non-null float64 68 secondary_cleaner.output.tail_au 14149 non-null float64 69 secondary_cleaner.state.floatbank2_a_air 13932 non-null float64 70 secondary_cleaner.state.floatbank2_a_level 14148 non-null float64 71 secondary_cleaner.state.floatbank2_b_air 14128 non-null float64 72 secondary_cleaner.state.floatbank2_b_level 14148 non-null float64 73 secondary_cleaner.state.floatbank3_a_air 14145 non-null float64 74 secondary_cleaner.state.floatbank3_a_level 14148 non-null float64 75 secondary_cleaner.state.floatbank3_b_air 14148 non-null float64 76 secondary_cleaner.state.floatbank3_b_level 14148 non-null float64 77 secondary_cleaner.state.floatbank4_a_air 14143 non-null float64 78 secondary_cleaner.state.floatbank4_a_level 14148 non-null float64 79 secondary_cleaner.state.floatbank4_b_air 14148 non-null float64 80 secondary_cleaner.state.floatbank4_b_level 14148 non-null float64 81 secondary_cleaner.state.floatbank5_a_air 14148 non-null float64 82 secondary_cleaner.state.floatbank5_a_level 14148 non-null float64 83 secondary_cleaner.state.floatbank5_b_air 14148 non-null float64 84 secondary_cleaner.state.floatbank5_b_level 14148 non-null float64 85 secondary_cleaner.state.floatbank6_a_air 14147 non-null float64 86 secondary_cleaner.state.floatbank6_a_level 14148 non-null float64 dtypes: datetime64[ns](1), float64(86) memory usage: 9.4 MB None В данных нет явных дубликатов В данных есть пропущенные значения
# test data
data_test = read_file('test')
| date | primary_cleaner.input.sulfate | primary_cleaner.input.depressant | primary_cleaner.input.feed_size | primary_cleaner.input.xanthate | primary_cleaner.state.floatbank8_a_air | primary_cleaner.state.floatbank8_a_level | primary_cleaner.state.floatbank8_b_air | primary_cleaner.state.floatbank8_b_level | primary_cleaner.state.floatbank8_c_air | primary_cleaner.state.floatbank8_c_level | primary_cleaner.state.floatbank8_d_air | primary_cleaner.state.floatbank8_d_level | rougher.input.feed_ag | rougher.input.feed_pb | rougher.input.feed_rate | rougher.input.feed_size | rougher.input.feed_sol | rougher.input.feed_au | rougher.input.floatbank10_sulfate | rougher.input.floatbank10_xanthate | rougher.input.floatbank11_sulfate | rougher.input.floatbank11_xanthate | rougher.state.floatbank10_a_air | rougher.state.floatbank10_a_level | rougher.state.floatbank10_b_air | rougher.state.floatbank10_b_level | rougher.state.floatbank10_c_air | rougher.state.floatbank10_c_level | rougher.state.floatbank10_d_air | rougher.state.floatbank10_d_level | rougher.state.floatbank10_e_air | rougher.state.floatbank10_e_level | rougher.state.floatbank10_f_air | rougher.state.floatbank10_f_level | secondary_cleaner.state.floatbank2_a_air | secondary_cleaner.state.floatbank2_a_level | secondary_cleaner.state.floatbank2_b_air | secondary_cleaner.state.floatbank2_b_level | secondary_cleaner.state.floatbank3_a_air | secondary_cleaner.state.floatbank3_a_level | secondary_cleaner.state.floatbank3_b_air | secondary_cleaner.state.floatbank3_b_level | secondary_cleaner.state.floatbank4_a_air | secondary_cleaner.state.floatbank4_a_level | secondary_cleaner.state.floatbank4_b_air | secondary_cleaner.state.floatbank4_b_level | secondary_cleaner.state.floatbank5_a_air | secondary_cleaner.state.floatbank5_a_level | secondary_cleaner.state.floatbank5_b_air | secondary_cleaner.state.floatbank5_b_level | secondary_cleaner.state.floatbank6_a_air | secondary_cleaner.state.floatbank6_a_level | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2016-09-01 00:59:59 | 210.8009 | 14.9931 | 8.0800 | 1.0050 | 1398.9813 | -500.2256 | 1399.1449 | -499.9197 | 1400.1030 | -500.7044 | 1399.0017 | -499.4851 | 13.1286 | 5.6367 | 489.7937 | 62.7105 | 42.0224 | 12.0841 | 16.9229 | 6.1535 | 16.8675 | 6.1507 | 1001.8493 | -350.3013 | 1249.7386 | -399.1075 | 1249.7505 | -399.3967 | 1198.2879 | -399.4886 | 999.4723 | -399.5310 | 949.5662 | -398.1808 | 24.9382 | -500.4910 | 14.9476 | -500.0138 | 20.0182 | -450.3960 | 13.9871 | -449.8315 | 12.0236 | -497.7958 | 8.0167 | -501.2891 | 7.9466 | -432.3178 | 4.8725 | -500.0374 | 26.7059 | -499.7094 |
| 1 | 2016-09-01 01:59:59 | 215.3925 | 14.9875 | 8.0800 | 0.9905 | 1398.7779 | -500.0574 | 1398.0554 | -499.7782 | 1396.1510 | -499.2402 | 1399.5081 | -500.4163 | 13.0363 | 5.5261 | 490.1045 | 61.9612 | 41.1879 | 11.9190 | 17.0025 | 5.9990 | 16.9961 | 6.0023 | 998.6908 | -350.4257 | 1248.3955 | -399.9460 | 1249.5145 | -399.6308 | 1200.5065 | -399.9424 | 1000.0021 | -399.4915 | 950.2000 | -405.7875 | 24.9235 | -499.8140 | 14.9309 | -500.7645 | 19.9885 | -450.1140 | 14.0930 | -450.0592 | 12.0581 | -498.6958 | 8.1310 | -499.6342 | 7.9583 | -525.8396 | 4.8789 | -500.1624 | 25.0199 | -499.8194 |
| 2 | 2016-09-01 02:59:59 | 215.2599 | 12.8849 | 7.7867 | 0.9960 | 1398.4937 | -500.8684 | 1398.8604 | -499.7645 | 1398.0757 | -502.1515 | 1399.4971 | -499.7155 | 13.1384 | 5.4266 | 489.6180 | 66.9038 | 42.5463 | 12.0913 | 16.9925 | 5.8506 | 16.9821 | 5.8536 | 998.5167 | -349.7835 | 1247.4407 | -400.2643 | 1248.2072 | -401.0744 | 1199.7700 | -400.7906 | 999.9255 | -399.2370 | 950.3205 | -400.8643 | 24.9087 | -500.3040 | 14.9965 | -500.9938 | 20.0397 | -450.2632 | 14.0779 | -449.6610 | 11.9624 | -498.7675 | 8.0969 | -500.8274 | 8.0711 | -500.8017 | 4.9051 | -499.8285 | 24.9949 | -500.6226 |
| 3 | 2016-09-01 03:59:59 | 215.3362 | 12.0068 | 7.6400 | 0.8635 | 1399.6181 | -498.8636 | 1397.4401 | -499.2110 | 1400.1293 | -498.3559 | 1401.0652 | -501.0387 | 12.4005 | 5.1148 | 476.6181 | 59.8659 | 41.0602 | 12.1816 | 16.5321 | 5.8019 | 16.5153 | 5.8037 | 1000.2766 | -350.1726 | 1251.3227 | -398.6553 | 1250.4937 | -399.7467 | 1199.3987 | -397.5031 | 1001.9307 | -400.4376 | 950.7353 | -399.8030 | 24.8940 | -499.3824 | 14.9167 | -499.8623 | 20.0311 | -449.3726 | 14.0140 | -449.5269 | 12.0331 | -498.3509 | 8.0749 | -499.4744 | 7.8971 | -500.8685 | 4.9314 | -499.9636 | 24.9489 | -498.7100 |
| 4 | 2016-09-01 04:59:59 | 199.0993 | 10.6825 | 7.5300 | 0.8056 | 1401.2681 | -500.8083 | 1398.1288 | -499.5045 | 1402.1722 | -500.8106 | 1399.4805 | -499.3741 | 11.3274 | 4.7674 | 488.2481 | 63.3153 | 41.2692 | 11.2904 | 13.6073 | 5.7381 | 13.6501 | 5.7396 | 996.5413 | -350.5625 | 1304.6588 | -399.5115 | 1306.4555 | -399.0507 | 1248.6993 | -400.8769 | 1058.8391 | -398.9882 | 949.6453 | -399.2776 | 24.8869 | -499.3574 | 14.9792 | -500.1868 | 19.9624 | -450.6388 | 14.0092 | -450.0223 | 12.0254 | -500.7865 | 8.0547 | -500.3975 | 8.1079 | -509.5267 | 4.9577 | -500.3600 | 25.0033 | -500.8563 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 5285 | 2017-12-31 19:59:59 | 173.9578 | 15.9634 | 8.0700 | 0.8967 | 1401.9306 | -499.7288 | 1401.4414 | -499.1934 | 1399.8103 | -499.5991 | 1400.3348 | -499.2435 | 11.6390 | 4.6953 | 521.6852 | 66.7585 | 42.0220 | 10.5545 | 10.1092 | 7.2039 | 10.1108 | 7.1982 | 1399.9353 | -299.9996 | 1049.6420 | -500.0749 | 951.9239 | -499.6488 | 852.3374 | -498.4644 | 851.4368 | -500.2856 | 851.4613 | -499.7356 | 21.9121 | -499.9152 | 19.9091 | -499.7349 | 24.9396 | -500.0985 | 12.9684 | -499.9520 | 13.9960 | -500.1575 | 12.0692 | -499.6733 | 7.9773 | -499.5161 | 5.9333 | -499.9660 | 8.9872 | -499.7559 |
| 5286 | 2017-12-31 20:59:59 | 172.9103 | 16.0026 | 8.0700 | 0.8965 | 1447.0757 | -494.7168 | 1448.8519 | -465.9630 | 1443.8904 | -503.5877 | 1447.6534 | -480.4038 | 11.3381 | 4.4784 | 530.1958 | 62.5607 | 41.0964 | 10.2541 | 9.9795 | 7.2009 | 9.9789 | 7.2020 | 1406.1223 | -299.0572 | 1055.7152 | -498.2502 | 956.8503 | -497.4039 | 855.3867 | -495.7027 | 852.0713 | -499.4428 | 851.3290 | -496.5798 | 25.3223 | -497.0350 | 23.3106 | -498.8926 | 26.3692 | -499.2224 | 17.7049 | -499.5457 | 16.7498 | -496.0315 | 13.3654 | -499.1227 | 9.2886 | -496.8930 | 7.3729 | -499.9430 | 8.9868 | -499.9038 |
| 5287 | 2017-12-31 21:59:59 | 171.1357 | 15.9937 | 8.0700 | 1.1660 | 1498.8362 | -501.7704 | 1499.5724 | -495.5163 | 1502.7492 | -520.6674 | 1502.5853 | -498.2602 | 11.2859 | 4.4053 | 546.3069 | 73.6475 | 41.0955 | 10.1691 | 10.1822 | 7.1963 | 10.1855 | 7.1987 | 1396.2031 | -300.2107 | 1047.8797 | -499.6042 | 948.9634 | -499.5496 | 856.3256 | -500.0956 | 850.6146 | -499.4737 | 850.2796 | -498.5084 | 29.0759 | -500.5284 | 26.8880 | -500.9758 | 28.0002 | -500.5659 | 22.9965 | -500.4776 | 19.9941 | -499.7913 | 15.1014 | -499.9363 | 10.9892 | -498.3479 | 9.0209 | -500.0404 | 8.9820 | -497.7899 |
| 5288 | 2017-12-31 22:59:59 | 179.6972 | 15.4390 | 8.0700 | 1.5011 | 1498.4662 | -500.4840 | 1497.9870 | -519.2003 | 1496.5690 | -487.4796 | 1502.6889 | -501.5697 | 11.2897 | 4.3435 | 547.3314 | 78.0664 | 41.7157 | 10.0712 | 10.7309 | 7.2001 | 10.7263 | 7.2008 | 1403.9423 | -300.0301 | 1049.8023 | -499.7956 | 950.7694 | -500.3746 | 847.6472 | -499.9203 | 849.4130 | -500.3805 | 850.0750 | -500.4782 | 29.1032 | -499.6927 | 27.0517 | -499.8583 | 27.9804 | -499.9072 | 23.0466 | -499.7449 | 19.9588 | -499.9587 | 15.0269 | -499.7231 | 11.0116 | -499.9850 | 9.0098 | -499.9379 | 9.0127 | -500.1543 |
| 5289 | 2017-12-31 23:59:59 | 181.5569 | 14.9958 | 8.0700 | 1.6235 | 1498.0963 | -499.7969 | 1501.7438 | -505.1469 | 1499.5360 | -492.4282 | 1499.6743 | -499.7667 | 10.9046 | 4.0906 | 564.5404 | 77.6787 | 40.8911 | 9.6973 | 10.7895 | 7.1958 | 10.7929 | 7.2010 | 1400.6115 | -299.9894 | 1052.7828 | -499.7630 | 950.7937 | -499.3572 | 850.6395 | -500.4338 | 850.3708 | -500.8194 | 850.6802 | -498.5392 | 29.0981 | -500.4299 | 26.8924 | -500.0871 | 28.0235 | -500.1704 | 23.0136 | -500.2188 | 20.0347 | -500.7286 | 14.9142 | -499.9485 | 10.9866 | -500.6580 | 8.9895 | -500.3376 | 8.9886 | -500.7649 |
5290 rows × 53 columns
<class 'pandas.core.frame.DataFrame'> RangeIndex: 5290 entries, 0 to 5289 Data columns (total 53 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 date 5290 non-null datetime64[ns] 1 primary_cleaner.input.sulfate 5286 non-null float64 2 primary_cleaner.input.depressant 5285 non-null float64 3 primary_cleaner.input.feed_size 5290 non-null float64 4 primary_cleaner.input.xanthate 5286 non-null float64 5 primary_cleaner.state.floatbank8_a_air 5290 non-null float64 6 primary_cleaner.state.floatbank8_a_level 5290 non-null float64 7 primary_cleaner.state.floatbank8_b_air 5290 non-null float64 8 primary_cleaner.state.floatbank8_b_level 5290 non-null float64 9 primary_cleaner.state.floatbank8_c_air 5290 non-null float64 10 primary_cleaner.state.floatbank8_c_level 5290 non-null float64 11 primary_cleaner.state.floatbank8_d_air 5290 non-null float64 12 primary_cleaner.state.floatbank8_d_level 5290 non-null float64 13 rougher.input.feed_ag 5290 non-null float64 14 rougher.input.feed_pb 5290 non-null float64 15 rougher.input.feed_rate 5287 non-null float64 16 rougher.input.feed_size 5289 non-null float64 17 rougher.input.feed_sol 5269 non-null float64 18 rougher.input.feed_au 5290 non-null float64 19 rougher.input.floatbank10_sulfate 5285 non-null float64 20 rougher.input.floatbank10_xanthate 5290 non-null float64 21 rougher.input.floatbank11_sulfate 5282 non-null float64 22 rougher.input.floatbank11_xanthate 5265 non-null float64 23 rougher.state.floatbank10_a_air 5290 non-null float64 24 rougher.state.floatbank10_a_level 5290 non-null float64 25 rougher.state.floatbank10_b_air 5290 non-null float64 26 rougher.state.floatbank10_b_level 5290 non-null float64 27 rougher.state.floatbank10_c_air 5290 non-null float64 28 rougher.state.floatbank10_c_level 5290 non-null float64 29 rougher.state.floatbank10_d_air 5290 non-null float64 30 rougher.state.floatbank10_d_level 5290 non-null float64 31 rougher.state.floatbank10_e_air 5290 non-null float64 32 rougher.state.floatbank10_e_level 5290 non-null float64 33 rougher.state.floatbank10_f_air 5290 non-null float64 34 rougher.state.floatbank10_f_level 5290 non-null float64 35 secondary_cleaner.state.floatbank2_a_air 5287 non-null float64 36 secondary_cleaner.state.floatbank2_a_level 5290 non-null float64 37 secondary_cleaner.state.floatbank2_b_air 5288 non-null float64 38 secondary_cleaner.state.floatbank2_b_level 5290 non-null float64 39 secondary_cleaner.state.floatbank3_a_air 5281 non-null float64 40 secondary_cleaner.state.floatbank3_a_level 5290 non-null float64 41 secondary_cleaner.state.floatbank3_b_air 5290 non-null float64 42 secondary_cleaner.state.floatbank3_b_level 5290 non-null float64 43 secondary_cleaner.state.floatbank4_a_air 5290 non-null float64 44 secondary_cleaner.state.floatbank4_a_level 5290 non-null float64 45 secondary_cleaner.state.floatbank4_b_air 5290 non-null float64 46 secondary_cleaner.state.floatbank4_b_level 5290 non-null float64 47 secondary_cleaner.state.floatbank5_a_air 5290 non-null float64 48 secondary_cleaner.state.floatbank5_a_level 5290 non-null float64 49 secondary_cleaner.state.floatbank5_b_air 5290 non-null float64 50 secondary_cleaner.state.floatbank5_b_level 5290 non-null float64 51 secondary_cleaner.state.floatbank6_a_air 5290 non-null float64 52 secondary_cleaner.state.floatbank6_a_level 5290 non-null float64 dtypes: datetime64[ns](1), float64(52) memory usage: 2.1 MB None В данных нет явных дубликатов В данных есть пропущенные значения
Посмотрим, какие данные были выделены для теста модели, а какие для обучения.
# percentage of data for test
f'Процент данных для теста: {len(data_test) / len(data_full):.0%}'
'Процент данных для теста: 27%'
# train and test data
ax=data_train.plot(x='date',
y='rougher.input.feed_au',
kind='scatter', c='gray', alpha=0.3, figsize=(15,5), label='Обучение')
data_test.plot(x='date',
y='rougher.input.feed_au',
kind='scatter', c='c', alpha=0.3, label='Тест', ax=ax)
plt.xlabel('Дата')
plt.ylabel('% золота в руде')
plt.legend(title='Данные для модели', loc='upper left')
plt.title('Изменение доли золота в руде', fontsize=14)
plt.show()
Вывод: В данных более 19 000 записей (партий обработки руды) без явных дубликатов с параметрами исходной руды, флотации и очистки за три года, с 2016 по 2018. В некоторых признаках есть пропуски. Данные разделены на обучающую и тестовую выборки в соотношении 73% к 27%. Для обучающей выборки взяты данные каждого кода, примерно одних и тех же месяцев, а вот для тестовой выборки взяты два периода - с конец 2016 и 2017 годов (примерно с сентября по январь).
Сравним обучающую и тестовую выборки на примере распределения размеров гранул сырья. Если распределения будут сильно отличаться друг от друга, оценка модели может быть неправильной и стоит переразбить данные на выборки.
# distribution histograms of feed sizes and au concentrations
fig, axs = plt.subplots(1, 2, figsize=(10, 4))
fig.suptitle("Сравнение выборок", fontsize="x-large")
sns.histplot(data=data_full, x='rougher.input.feed_size', kde=True, stat= 'density',
color="salmon", ax=axs[0])
sns.histplot(data=data_train, x='rougher.input.feed_size', kde=True, stat= 'density',
color="skyblue", ax=axs[0])
sns.histplot(data=data_test, x='rougher.input.feed_size', kde=True, stat= 'density',
color="green", ax=axs[0]).set(xlabel='Размер гранул сырья',
ylabel=None, xlim=(0, 150))
sns.histplot(data=data_full, x='rougher.input.feed_au', kde=True, stat= 'density',
color="salmon", ax=axs[1])
sns.histplot(data=data_train, x='rougher.input.feed_au', kde=True, stat= 'density',
color="skyblue", ax=axs[1])
sns.histplot(data=data_test, x='rougher.input.feed_au', kde=True, stat= 'density',
color="green", ax=axs[1]).set(xlabel='Доля золота в руде',
ylabel=None, xlim=(0, 20))
plt.legend(labels=["Полные данные",
"Обучающие данные",
"Тестовые данные"],
bbox_to_anchor=(1.01, 1), loc='upper left', borderaxespad=0)
plt.show()
Вывод: Судя по распределению размеров гранул сырья и количеству золота в руде, обучающая выборка очень похожа на весь набор данных. Тестовая выборка несколько отличается - для размера гранул она больше скошена вправо, а для распределения концентрации золота - влево. При этом в тестовой выборке преобладают значение с более высоким содержанием золота, по сравнению с обучающей выборкой. Тем не менее, диапазон значений схож и, так как мы имеем "фиксированное" разделение на тестовую и обучающую выборки, оставим их как есть.
Известно, что в тестовой выборке отсутствуют некоторые признаки, так как для прогнозирования целевых переменных нам доступны лишь "входные" данные, а некоторые параметры замеряются и/или рассчитываются значительно позже. В тестовых данных 53 признака, а в обучающих и исходных - 87, включая целевые. Посмотрим, каких признаков нет в тестовых данных.
# features unavalable in the test data
set(data_train) - set(data_test)
{'final.output.concentrate_ag',
'final.output.concentrate_au',
'final.output.concentrate_pb',
'final.output.concentrate_sol',
'final.output.recovery',
'final.output.tail_ag',
'final.output.tail_au',
'final.output.tail_pb',
'final.output.tail_sol',
'primary_cleaner.output.concentrate_ag',
'primary_cleaner.output.concentrate_au',
'primary_cleaner.output.concentrate_pb',
'primary_cleaner.output.concentrate_sol',
'primary_cleaner.output.tail_ag',
'primary_cleaner.output.tail_au',
'primary_cleaner.output.tail_pb',
'primary_cleaner.output.tail_sol',
'rougher.calculation.au_pb_ratio',
'rougher.calculation.floatbank10_sulfate_to_au_feed',
'rougher.calculation.floatbank11_sulfate_to_au_feed',
'rougher.calculation.sulfate_to_au_concentrate',
'rougher.output.concentrate_ag',
'rougher.output.concentrate_au',
'rougher.output.concentrate_pb',
'rougher.output.concentrate_sol',
'rougher.output.recovery',
'rougher.output.tail_ag',
'rougher.output.tail_au',
'rougher.output.tail_pb',
'rougher.output.tail_sol',
'secondary_cleaner.output.tail_ag',
'secondary_cleaner.output.tail_au',
'secondary_cleaner.output.tail_pb',
'secondary_cleaner.output.tail_sol'}
В тестовых данных, как и ожидалось, отсутствуют все "выходные" данные каждой технологической стадии процесса и рассчеты на их основе. Такие же переменные стоит оставить и в обучающей выборке.
Добавим в тестовые данные целевые переменные rougher.output.recovery и final.output.recovery и удалим из обучающего сета признаки, которых нет в тестовом.
# add targets to the test dataset
data_test = data_test.merge(
data_full[
['date', 'rougher.output.recovery', 'final.output.recovery']],
on='date', how='left')
data_test.shape
(5290, 55)
# drop "output" features from the train dataset
data_train = data_train[list(data_test)]
data_train.shape
(14149, 55)
Теперь для подготовки модели у нас есть обучающая и тестовая выборки с одинаковыми столбцами. В данных имеются пропуски, которые перед обучением моделей стоит обработать. Обработку пропусков и возможных выбросов проведем после исседовательского анализа данных.
Перед обучением модели стоит проверить, правильно ли в данных рассчитаны целевые переменные rougher.output.recovery и final.output.recovery, так как от этого будет зависеть результат.
Расчёт эффективности
Эффективность обогащения рассчитывается по формуле
$$Recovery = C * (F - T) / (F * (C - T)) * 100\%$$где:
Создадим функцию для рассчета коэффициента восстановления.
# function for calculation of Recovery
def recovery(df, c, f, t):
"""Функция рассчитывает эффективность обогащения.
Принимает на вход:
df - датафрейм;
с — строку с названием столбца с долей золота в концентрате
ПОСЛЕ флотации/очистки;
f — строку с названием столбца с долей золота в сырье/концентрате
ДО флотации/очистки;
t — строку с названием столбца с долей золота в отвальных хвостах
после флотации/очистки.
Возвращает pd.Series c коэффициентами эффективности обогащения.
"""
rec = (df[c] * (df[f]-df[t])
.div(df[f]*(df[c]-df[t]))
.mul(100))
return rec
# calculation of recovery after rougher process
rec_rougher = recovery(data_full,
'rougher.output.concentrate_au',
'rougher.input.feed_au',
'rougher.output.tail_au')
# calculation of final Recovery
rec_final = recovery(data_full,
'final.output.concentrate_au',
'rougher.input.feed_au',
'final.output.tail_au')
print('Средний коэффициент эффективности обогащения:')
print()
print('Черновой концентрат:')
print(f'Рассчеты {rec_rougher.mean():.2f}')
print(f'Данные {data_full["rougher.output.recovery"].mean():.2f}')
print(f'MAE: {mean_absolute_error(data_full["rougher.output.recovery"], rec_rougher):.4f}')
print()
print('Финальный продукт:')
print(f'Рассчеты {rec_final.mean():.2f}')
print(f'Данные {data_full["final.output.recovery"].mean():.2f}')
print(f'MAE: {mean_absolute_error(data_full["final.output.recovery"], rec_final):.4f}')
Средний коэффициент эффективности обогащения: Черновой концентрат: Рассчеты 83.33 Данные 83.33 MAE: 0.0000 Финальный продукт: Рассчеты 67.05 Данные 67.05 MAE: 0.0000
Вывод: целевые переменные в данных рассчитаны верно. Ошибка практически нулевая. Коэффициент эффективности обогащения для чернового концентрата составляет 83%, а для всего процесса - 67%.
Анализ данных проведем на целом датасете. Посмотрим, как различные признаки на разных стадиях влияют друг на друга и на целевые переменные.
Целевыми переменными являются рассчитанные коэффициенты эффективности обогащения для чернового концентрата rougher.output.recovery и для всего процесса final.output.recovery.
Данные переменные зависят от доли золота в черновом концентрате/финальном концентрате, доли золота в руде и отвальных хвостах.
# boxplots
data_full[['rougher.output.recovery', 'final.output.recovery']].plot(
kind='box', title='Коэффициенты обогащения', figsize=(10,5))
plt.ylabel('%')
plt.xticks([1,2], ['Черновой концентрат', 'Финальный продукт'])
plt.show()
#descriptive statistics
data_full[['rougher.output.recovery', 'final.output.recovery']].describe()
| rougher.output.recovery | final.output.recovery | |
|---|---|---|
| count | 19439.0000 | 19439.0000 |
| mean | 83.3286 | 67.0502 |
| std | 14.1481 | 10.1258 |
| min | 0.0000 | 0.0000 |
| 25% | 81.0380 | 63.2997 |
| 50% | 86.1889 | 68.1727 |
| 75% | 90.0107 | 72.6866 |
| max | 100.0000 | 100.0000 |
Коэффициент обогащения чернового концентрата в среднем составляет около 80%, для большинства случаев (трех четвертей) не превышает 90%. Для финального продукта эти цифры составляют 67% и 73% соответсвенно.
В целевых переменных rougher.output.recovery и final.output.recovery есть нулевые значения, что говорит о том, что были нулевые значения доли золота в черновом концентрате или финальном концентратах (в руде не было нулевых значений доли золота). Проанализируем эти значения, посмотрим для них на содержание золота и других металлов в руде и после флотации/очистки. Причина может быть в незаполнении этих показателей по каким-либо технологическим причинам, поскольку количество золота в руде ненулевое во всех случаях.
Также есть значения 100% восстановления золота, что странно, стоит их также проанализировать.
Нулевые значения коэффициентов обогащения
# boxplots
data_full[['rougher.output.concentrate_au',
'rougher.output.tail_au',
'final.output.concentrate_au',
'final.output.tail_au']].plot(
kind='box', title='Распределения долей золота', figsize=(10,5))
plt.ylabel('%')
plt.xticks([1,2,3,4], ['Черновой концентрат',
'Черновые отвалы',
'Финальный продукт',
'Финальные отвалы'])
plt.show()
data_full[['rougher.output.concentrate_au',
'rougher.output.tail_au',
'final.output.concentrate_au',
'final.output.tail_au']].describe()
| rougher.output.concentrate_au | rougher.output.tail_au | final.output.concentrate_au | final.output.tail_au | |
|---|---|---|---|---|
| count | 19439.0000 | 19439.0000 | 19439.0000 | 19439.0000 |
| mean | 19.7720 | 1.8164 | 44.0765 | 3.0425 |
| std | 3.7536 | 0.6800 | 5.1298 | 0.9228 |
| min | 0.0000 | 0.0207 | 0.0000 | 0.0000 |
| 25% | 18.8025 | 1.4042 | 43.4022 | 2.4611 |
| 50% | 20.2802 | 1.8082 | 45.0112 | 2.9849 |
| 75% | 21.7178 | 2.2119 | 46.2753 | 3.5714 |
| max | 28.8245 | 9.6890 | 52.7566 | 8.2450 |
Видно, что как в черновом, так и в финальном концентрате имеются нулевые значения доли золота, это, вероятно, является причиной нулевых значений коэффициентов восстановления. Сначала посмотрим на такие значения в черновом концентрате.
print('Процент данных с нулевым содержанием золота в черновом концентрате:')
print(f'{len(data_full[data_full["rougher.output.concentrate_au"] < 0.001])/len(data_full):.2%}')
Процент данных с нулевым содержанием золота в черновом концентрате: 2.03%
Посмотрим на другие признаки при "нулевых" концентрациях золота в черновом концентрате.
# [Au]=0 in rougher_output
data_full[data_full['rougher.output.concentrate_au'] < 0.001][['rougher.input.feed_au',
'rougher.output.concentrate_au',
'rougher.output.tail_au',
'rougher.output.recovery']]
| rougher.input.feed_au | rougher.output.concentrate_au | rougher.output.tail_au | rougher.output.recovery | |
|---|---|---|---|---|
| 45 | 7.1141 | 0.0 | 1.9398 | 0.0 |
| 46 | 7.6515 | 0.0 | 2.0876 | 0.0 |
| 47 | 5.5877 | 0.0 | 2.1265 | 0.0 |
| 48 | 4.7530 | 0.0 | 1.9389 | 0.0 |
| 49 | 5.1228 | 0.0 | 2.0509 | 0.0 |
| ... | ... | ... | ... | ... |
| 15620 | 7.9511 | 0.0 | 0.7419 | 0.0 |
| 15621 | 8.7158 | 0.0 | 0.8280 | 0.0 |
| 15622 | 9.0261 | 0.0 | 1.0514 | 0.0 |
| 15623 | 8.7524 | 0.0 | 1.0643 | 0.0 |
| 15624 | 8.4676 | 0.0 | 1.0667 | 0.0 |
394 rows × 4 columns
# [Au]=0 in rougher_output, time distribution
ax = data_full.plot(x='date',
y='rougher.input.feed_au',
kind='scatter', c='gray', alpha=0.2, figsize=(15,5), label='ненулевая')
data_full[data_full['rougher.output.concentrate_au'] < 0.001].plot(
x='date', y='rougher.input.feed_au', kind='scatter', c='r', ax=ax,
label='нулевая')
plt.xlabel('Дата')
plt.ylabel('% золота в руде')
plt.legend(title='Доля золота в черновом концентрате')
plt.title('Распределение "нулевых" долей золота в черновом концентрате')
plt.show()
Нулевые значения количества золота (2% данных) в черновом концентрате, вероятно, обусловлены какими-то технологическими ошибками, видно, что они появляются в основном "кластерами", и при этом количество золота в руде и отвальных хвостах ненулевое. Эти ошибки вызывают появление нулевых значений коэффициента обогащения, которые стоит обработать.
Можно видеть, что и у финального коэффициента обогащения есть нулевые значения, причиной этого также могут быть нулевые значения финальной концентрации золота. Проверим это.
print('Процент данных с нулевой концентрацией золота на финальной стадии:')
print(f'{len(data_full[data_full["final.output.concentrate_au"] < 0.001])/len(data_full):.2%}')
Процент данных с нулевой концентрацией золота на финальной стадии: 0.50%
# [Au]=0 in final.output
data_full[data_full['final.output.concentrate_au'] < 0.001][['rougher.input.feed_au',
'final.output.concentrate_au',
'final.output.tail_au',
'rougher.output.recovery',
'final.output.recovery']]
| rougher.input.feed_au | final.output.concentrate_au | final.output.tail_au | rougher.output.recovery | final.output.recovery | |
|---|---|---|---|---|---|
| 644 | 5.5990 | 0.0 | 1.7791 | 68.9610 | 0.0 |
| 1193 | 7.7861 | 0.0 | 2.9845 | 82.7873 | 0.0 |
| 1194 | 7.4992 | 0.0 | 2.7473 | 83.5153 | 0.0 |
| 1195 | 7.0323 | 0.0 | 2.7914 | 83.7022 | 0.0 |
| 1196 | 7.0216 | 0.0 | 2.6821 | 84.8368 | 0.0 |
| ... | ... | ... | ... | ... | ... |
| 14951 | 11.6048 | 0.0 | 5.0618 | 79.7052 | 0.0 |
| 14952 | 11.7636 | 0.0 | 4.2916 | 83.3258 | 0.0 |
| 15183 | 7.3455 | 0.0 | 5.8195 | 26.9599 | 0.0 |
| 15184 | 7.6878 | 0.0 | 3.8373 | 78.7868 | 0.0 |
| 15310 | 6.0094 | 0.0 | 1.2109 | 65.0039 | 0.0 |
98 rows × 5 columns
# [Au]=0 in final.output, time distribution
ax = data_full.plot(x='date',
y='rougher.input.feed_au',
kind='scatter', c='gray', alpha=0.2,
figsize=(15,5), label='ненулевая')
data_full[data_full['final.output.concentrate_au'] < 0.001].plot(
x='date', y='rougher.input.feed_au', kind='scatter', c='r',
ax=ax, label='нулевая')
plt.xlabel('Дата')
plt.ylabel('% золота в руде')
plt.legend(title='Доля золота в финальном продукте')
plt.title('Распределение "нулевых" долей золота в финальном продукте')
plt.show()
Нулевые значения количества золота в финальном продукте (0.5% данных) разбросаны по всем данным и, вероятно, также обусловлены какими-то технологическими ошибками. При этом количество золота в руде и отвальных хвостах ненулевое. Эти ошибки вызывают появление нулевых значений финального коэффициента обогащения, которые стоит обработать перед обучением модели.
100% коэффициенты обогащения
Имеются значения коэффициентов обогащения, равные 100%, что также подозрительно. Изучим их для чернового концентрата и финального сырья.
print('Процент данных с 100% обогащением, черновой концентрат:')
print(f'{len(data_full[data_full["rougher.output.recovery"] > 99.99])/len(data_full):.2%}')
Процент данных с 100% обогащением, черновой концентрат: 0.03%
# [Au]=100 in rougher_output
data_full[data_full['rougher.output.recovery'] > 99.99][['rougher.input.feed_au',
'rougher.output.concentrate_au',
'rougher.output.tail_au',
'rougher.output.recovery']]
| rougher.input.feed_au | rougher.output.concentrate_au | rougher.output.tail_au | rougher.output.recovery | |
|---|---|---|---|---|
| 16226 | 0.01 | 0.01 | 1.3525 | 100.0 |
| 16227 | 0.01 | 0.01 | 1.3525 | 100.0 |
| 16228 | 0.01 | 0.01 | 1.3525 | 100.0 |
| 16229 | 0.01 | 0.01 | 1.3525 | 100.0 |
| 16230 | 0.01 | 0.01 | 1.3525 | 100.0 |
В данных всего 5 значений, когда коэффициент обогащения черновоко концентрата равен 100%, в этом случае доля золота в руде равна доле в черновом концентрате. Это похоже на ошибочные значения.
print('Процент данных с 100% обогащением на финальной стадии:')
print(f'{len(data_full[data_full["final.output.recovery"] > 99.99])/len(data_full):.2%}')
Процент данных с 100% обогащением на финальной стадии: 0.47%
# [Au]=100 in final.output
data_full[data_full['final.output.recovery'] > 99.99][['rougher.output.concentrate_au',
'primary_cleaner.output.concentrate_au',
'final.output.concentrate_au',
'final.output.tail_au',
'final.output.recovery']]
| rougher.output.concentrate_au | primary_cleaner.output.concentrate_au | final.output.concentrate_au | final.output.tail_au | final.output.recovery | |
|---|---|---|---|---|---|
| 75 | 18.8615 | 5.9645 | 46.5433 | 0.0 | 100.0 |
| 1916 | 22.0130 | 10.3694 | 25.7735 | 0.0 | 100.0 |
| 1927 | 19.0389 | 34.1149 | 42.9840 | 0.0 | 100.0 |
| 2017 | 24.8120 | 28.5552 | 38.4562 | 0.0 | 100.0 |
| 3388 | 16.9222 | 25.1345 | 42.7182 | 0.0 | 100.0 |
| ... | ... | ... | ... | ... | ... |
| 18326 | 17.4802 | 35.1516 | 46.5568 | 0.0 | 100.0 |
| 18420 | 17.2792 | 28.7369 | 40.5272 | 0.0 | 100.0 |
| 19082 | 21.3183 | 35.4653 | 32.2661 | 0.0 | 100.0 |
| 19209 | 24.4854 | 30.8070 | 1.0640 | 0.0 | 100.0 |
| 19210 | 22.5045 | 32.5089 | 41.1188 | 0.0 | 100.0 |
91 rows × 5 columns
Видно, что 100% обогащение на финальной стадии является следствием нулевой концентрации золота в финальных отвальных хвостах. Посмотрим, как они распределены.
# [Au]=100 in final.output, time distribution
ax = data_full.plot(x='date',
y='rougher.input.feed_au',
kind='scatter', c='gray', alpha=0.2,
figsize=(15,5), label='ненулевые')
data_full[data_full['final.output.tail_au'] < 0.001].plot(
x='date', y='rougher.input.feed_au', kind='scatter', c='r',
ax=ax, label='нулевые')
plt.xlabel('Дата')
plt.ylabel('% золота в руде')
plt.legend(title='Доля золота в отвальных хвостах')
plt.title('Распределение "нулевых" долей золота в финальных отвальных хвостах')
plt.show()
Нулевые значения количества золота в отвальных хвостах (0.47% данных) разбросаны по всем данным, а в паре случаев собраны в "кластеры". Это, вероятно, также следствие каких-то технологических ошибок. При этом концентрация золота после флотации, первой и второй очисток ненулевое. Эти ошибки вызывают появление нулевых значений финального коэффициента обогащения, которые стоит обработать перед обучением модели.
Вывод: кажется, что как для чернового концентрата, так и для финального сырья нулевые и 100% значения коэффициентов обогащения являются ошибочными и их стоит обработать перед обучением модели.
# scatterplots and distribution histograms, rougher
sns.pairplot(data_full[['rougher.input.feed_size',
'rougher.input.feed_rate',
'rougher.output.recovery']])
<seaborn.axisgrid.PairGrid at 0x275b2e4abe0>
# scatterplots and distribution histograms, primary_cleaner
sns.pairplot(data_full[['primary_cleaner.input.feed_size',
'primary_cleaner.output.concentrate_au',
'primary_cleaner.output.tail_au',
'final.output.recovery']])
<seaborn.axisgrid.PairGrid at 0x275b15edc70>
# descriptive statistics
data_full[['rougher.input.feed_size',
'rougher.input.feed_rate',
'primary_cleaner.input.feed_size',
'rougher.output.recovery',
'final.output.recovery']].describe()
| rougher.input.feed_size | rougher.input.feed_rate | primary_cleaner.input.feed_size | rougher.output.recovery | final.output.recovery | |
|---|---|---|---|---|---|
| count | 19294.0000 | 19428.0000 | 19439.0000 | 19439.0000 | 19439.0000 |
| mean | 58.9703 | 478.3200 | 7.3071 | 83.3286 | 67.0502 |
| std | 21.6345 | 105.3738 | 0.6135 | 14.1481 | 10.1258 |
| min | 0.0464 | 0.0030 | 1.0800 | 0.0000 | 0.0000 |
| 25% | 47.4351 | 416.5255 | 6.9400 | 81.0380 | 63.2997 |
| 50% | 54.6102 | 499.4161 | 7.2800 | 86.1889 | 68.1727 |
| 75% | 65.0230 | 550.1722 | 7.6700 | 90.0107 | 72.6866 |
| max | 484.9675 | 717.5088 | 15.5000 | 100.0000 | 100.0000 |
Вывод: Явно выраженного сильного влияния скорости подачи и размера гранул руды на коэффициент обогащения чернового концентрата не наблюдается, однако прослеживается некоторая тенденция - увеличение этого показателя при снижении скорости подачи и большем размере гранул.
Разброс размера гранул тут большой, в основном размер гранул около 60, и, как правило, не превышает 100, но есть выбросы и до почти 500, а минимальные значения около 0. Скорость подачи сырья в большинстве случаев от 200 до 600 (но есть пики около 0, 200, 400...).
Размер гранул чернового концетрата перед очисткой не оказывает особого влияния ни на концентрацию золота в продукте очистки и отвальных хвостах, ни на финальный коэффициент обогащения. Стоит отметить, что после флотации размер гранул более однородный (стандартное отклонение всего 0.6, в отличие от 22 перед флотацией), он более чем в 8 раз меньше и в среднем составляет около 7.
Сначала посмотрим на стадию флотации.
# scatterplots and distribution histograms, rougher
sns.pairplot(data_full[['rougher.input.floatbank10_sulfate',
'rougher.input.floatbank10_xanthate',
'rougher.input.floatbank11_sulfate',
'rougher.input.floatbank11_xanthate',
'rougher.output.recovery']])
<seaborn.axisgrid.PairGrid at 0x275b40d0fd0>
Изучим подробнее влияние флотационных реагентов на эффективность обогащения чернового концентрата.
# scatterplot
plt.scatter(data_full['rougher.input.feed_au'],
data_full['rougher.output.recovery'],
c=data_full['rougher.input.floatbank10_sulfate'],
alpha = .5, cmap = 'viridis',
vmin=5, vmax=20
)
plt.colorbar(label='Количество сульфидов')
plt.title('Черновой концентрат')
plt.xlabel('Доля золота в руде, %')
plt.ylabel('Коэффициент обогащения, %')
plt.show()
# scatterplot
plt.scatter(data_full['rougher.input.feed_au'],
data_full['rougher.output.recovery'],
c=data_full['rougher.input.floatbank10_xanthate'],
alpha = .5, cmap = 'viridis',
vmin=1, vmax=9
)
plt.colorbar(label='Количество ксантогенатов')
plt.title('Черновой концентрат')
plt.xlabel('Доля золота в руде, %')
plt.ylabel('Коэффициент обогащения, %')
plt.show()
Вывод: количество флотационных реагентов некоторым образом влияет на коэффициент обогащения чернового концентрата, в большей степени - сульфида натрия. Флотационные установки достаточно "похожи" в этом ключе, поэтому одну из них можно исключить. Количество сульфида натрия и ксантогенатов связаны - чем больше одного реагента, тем больше и другого. Больше всего с высоким коэффициентом извлечения золота из бедных руд связано количество флотационного реагента сульфида натрия, для таких руд оно минимально.
Посмотрим, как связано количество флотационных реагентов при флотации и перед очисткой, и влияет ли содержание флотационных реагентов перед очисткой на финальный коэффициент обогащения.
# scatterplots and distribution histograms
sns.pairplot(data_full[['rougher.input.floatbank10_sulfate',
'rougher.input.floatbank10_xanthate',
'primary_cleaner.input.sulfate',
'primary_cleaner.input.depressant',
'primary_cleaner.input.xanthate',
'final.output.recovery']])
<seaborn.axisgrid.PairGrid at 0x275b8ede970>
# scatterplot
plt.scatter(data_full['rougher.output.concentrate_au'],
data_full['final.output.recovery'],
c=data_full['primary_cleaner.input.sulfate'],
alpha = .5, cmap = 'viridis',
vmin=25, vmax=250
)
plt.colorbar(label='Количество сульфидов')
plt.title('Финальный продукт')
plt.xlabel('Доля золота в черновом концентрате, %')
plt.ylabel('Коэффициент обогащения, %')
plt.show()
# scatterplot
plt.scatter(data_full['rougher.output.concentrate_au'],
data_full['final.output.recovery'],
c=data_full['primary_cleaner.input.xanthate'],
alpha = .5, cmap = 'viridis',
vmin=1, vmax=2
)
plt.colorbar(label='Количество ксантогенатов')
plt.title('Финальный продукт')
plt.xlabel('Доля золота в черновом концентрате, %')
plt.ylabel('Коэффициент обогащения, %')
plt.show()
Вывод: Как правило, чем больше ксантогенатов в черновом концентрате перед очисткой, тем больше сульфида натрия.
Количество сульфида натрия и ксантогенатов в черновом концентрате перед очисткой некоторым образом влияет и на финальный коэффициент обогащения. Влияние ксантогенатов кажется более выраженным. Количество сульфидов во время флотации линейно связано с их количеством перед очисткой и некоторым образом с количеством ксантогенатов перед очисткой.
Не видно зависимости между финальным коэффициентом обогащения и долей золота в черновом концентрате, а также участия в этой взаимосвязи флотационных реагентов.
Посмотрим на влияние объема воздуха и уровня жидкости во флотационных и очистительных установках на коэффициенты обогащения. Сначала посмотрим на стадию флотации и объем подаваемого воздуха.
# distribution histograms, rougher
data_full[['rougher.state.floatbank10_a_air',
'rougher.state.floatbank10_b_air',
'rougher.state.floatbank10_c_air',
'rougher.state.floatbank10_d_air',
'rougher.state.floatbank10_e_air',
'rougher.state.floatbank10_f_air']].hist(bins=100, figsize=(10, 10))
plt.show()
В целом, разные флотационные установки схожи по объему подаваемого воздуха, за исключением 10_a. Для анализа можно выбрать какую-то одну, например, 10_b (репрезентативное симметричное распределение).
Посмотрим на уровень жидкости.
# distribution histograms, rougher
data_full[['rougher.state.floatbank10_a_level',
'rougher.state.floatbank10_b_level',
'rougher.state.floatbank10_c_level',
'rougher.state.floatbank10_d_level',
'rougher.state.floatbank10_e_level',
'rougher.state.floatbank10_f_level']].hist(bins=100, figsize=(10, 10))
plt.show()
Флотационные установки схожи по уровню жидкости, опять же, за исключением 10_а. Также выберем одну - 10_b.
# scatterplots and distribution histograms, rougher
sns.pairplot(data_full[['rougher.state.floatbank10_b_air',
'rougher.state.floatbank10_b_level',
'rougher.output.recovery']])
<seaborn.axisgrid.PairGrid at 0x275bd831be0>
# scatterplot
plt.scatter(data_full['rougher.input.feed_au'],
data_full['rougher.output.recovery'],
c=data_full['rougher.state.floatbank10_b_air'],
alpha = .5, cmap = 'viridis')
plt.colorbar(label='объема воздуха')
plt.title('Черновой концентрат')
plt.xlabel('Доля золота в руде, %')
plt.ylabel('Коэффициент обогащения, %')
plt.show()
# scatterplot
plt.scatter(data_full['rougher.input.feed_au'],
data_full['rougher.output.recovery'],
c=data_full['rougher.state.floatbank10_b_level'],
alpha = .5, cmap = 'viridis')
plt.colorbar(label='Уровень жидкости')
plt.title('Черновой концентрат')
plt.xlabel('Доля золота в руде, %')
plt.ylabel('Коэффициент обогащения, %')
plt.show()
Вывод: Видно, что больше всего с высоким коэффициентом извлечения золота из бедных руд связано количество флотационного реагента сульфида натрия, для таких руд оно минимально. Таким образом, этот признак будет важным для модели. Для других "участников" процесса флотации такого влияния не видно.
Вывод: кажется, что объем воздуха не сильно влияет на коэффициент обогащения чернового концентрата, а вот с уровнем воды прослеживается некоторая тенденция связи. При более высоких уровнях минимальный коэффициент обогащения чернового концентрата выше.
Посмотрим, влияют ли физические факторы на финальный коэффициент обогащения. Поскольку мы видели, что флотационные установки схожи, выберем лишь какую-то одну для каждого этапа очистки.
# scatterplots and distribution histograms, primary_cleaner
sns.pairplot(data_full[['primary_cleaner.state.floatbank8_b_air',
'primary_cleaner.state.floatbank8_b_level',
'final.output.recovery']], diag_kind='kde')
<seaborn.axisgrid.PairGrid at 0x275bef607c0>
# scatterplots and distribution histograms, secondary_cleaner
sns.pairplot(data_full[['secondary_cleaner.state.floatbank3_b_air',
'secondary_cleaner.state.floatbank3_b_level',
'final.output.recovery']], diag_kind='kde')
<seaborn.axisgrid.PairGrid at 0x275bf514a00>
Вывод: кажется, что объем воздуха и уровень жидкости в установках на стадиях очистки не сильно влияет на финальный коэффициент обогащения.
Из данных видно, что попутными компонентами этой золотоносной руды являются серебро (ag), свинец (pb) и, вероятно, зольные компоненты (sol). Эффективность работы обогатительных фабрик во многом зависит от качества перерабатываемого сырья. Посмотрим, как связана доля металлов руде с коэффициентами обогащения золота.
# scatterplots and distribution histograms, rougher
sns.pairplot(data_full[['rougher.input.feed_au',
'rougher.input.feed_ag',
'rougher.input.feed_pb',
'rougher.input.feed_sol',
'rougher.output.recovery',
'final.output.recovery']])
<seaborn.axisgrid.PairGrid at 0x275bfb94880>
# descriptive statistics
data_full[['rougher.input.feed_au',
'rougher.input.feed_ag',
'rougher.input.feed_pb',
'rougher.input.feed_sol']].describe()
| rougher.input.feed_au | rougher.input.feed_ag | rougher.input.feed_pb | rougher.input.feed_sol | |
|---|---|---|---|---|
| count | 19439.0000 | 19439.0000 | 19339.0000 | 19340.0000 |
| mean | 8.2661 | 8.7949 | 3.5981 | 36.6951 |
| std | 1.9551 | 1.9368 | 1.0495 | 5.1454 |
| min | 0.0100 | 0.0100 | 0.0100 | 0.0100 |
| 25% | 6.8544 | 7.2380 | 2.8873 | 34.2078 |
| 50% | 8.1258 | 8.5936 | 3.5349 | 37.2026 |
| 75% | 9.7699 | 10.2138 | 4.2442 | 40.0391 |
| max | 13.7313 | 14.5960 | 7.1426 | 53.4777 |
Мы видели, что есть руды, с более бедным содержанием золота, но достаточно высоким коэффициентом обогащения, проверим предположение, что в отвальных хвостах таких руд содержится меньше золота, а значит оно лучше извлекается.
# scatterplot
plt.scatter(data_full['rougher.input.feed_au'],
data_full['rougher.output.concentrate_au'],
c=data_full['rougher.output.tail_au'],
alpha = .5, cmap = 'viridis',
vmin=0, vmax=8
)
plt.colorbar(label='Отвальные хвосты')
plt.title('Доля золота, %')
plt.xlabel('Руда')
plt.ylabel('Черновой концентрат')
plt.show()
Действительно, видно, что для некоторых руд с меньшей долей золота, его доля в "отвальных хвостах" также минимальна (тут, конечно, играет роль и тот факт, если параметры обогащения схожи, что чем меньше золота в руде, тем меньше его будет и в отвальных хвостах).
Посмотрим на коэффициенты корреляции между долями компонентов в руде и коэффициентами обогащения.
# Phik correlation coefficients matrix
phik_overview = data_full[['rougher.input.feed_au',
'rougher.input.feed_ag',
'rougher.input.feed_pb',
'rougher.input.feed_sol',
'rougher.output.recovery',
'final.output.recovery']].phik_matrix()
interval columns not set, guessing: ['rougher.input.feed_au', 'rougher.input.feed_ag', 'rougher.input.feed_pb', 'rougher.input.feed_sol', 'rougher.output.recovery', 'final.output.recovery']
# Plot Phik correlation coefficients matrix
plot_correlation_matrix(phik_overview.values,
x_labels=('feed_au', 'feed_ag', 'feed_pb', 'feed_sol',
'rougher_recovery', 'final_recovery'),
y_labels=('feed_au', 'feed_ag', 'feed_pb', 'feed_sol',
'rougher_recovery', 'final_recovery'),
title="Phik correlation coefficients",
figsize=(10, 5),
vmin=0, vmax=1)
Как было видно из гистограмм распределения, есть сильная корреляция между количеством золота в руде и количеством серебра, чуть меньшая - с количеством свинца. Коэффициент обогащения чернового концентрата имеет умеренную корреляцию с количеством каждого металла и зольного компонента в руде (около 0.5), а финальный коэффициент обогащения более слабо коррелирует с количеством компонентов в руде (наиболее выражено - для золота и серебра).
Вывод: Видна некоторая закономерная связь между количеством металлов в руде и коэффициентом обогащения чернового концентрата - чем больше доля металлов в сырье, тем больше коэффициент обогащения. Но связь не четко линейная, видно, что иногда из более бедных руд можно извлечь почти все золото. Вероятно, из некоторого сырья золото извлекается проще, в таком случае меньше золота будет в отвальных хвостах. Вероятно, важную роль тут могут играть другие факторы технологического процесса - количество флотационных реагентов, возможно, физические параметры. Видна такая зависимость - если в руде есть определенная доля цветного металла, то можно рассчитывать на определенный минимальный коэффициент обогащения, в зависимости от руды и условий он может быть значительно выше, но, как праввило, не будет ниже.
На финальный коэффициент обогащения содержание металлов в руде влияет не так сильно, что может быть следствием как раз разной эффективности извлечения металлов из руды. Прослеживается некоторая зависимость для золота (что логично) и серебра, для свинца - почти не видно влияния. Зольные компоненты на коэффициенты обогащения не влияют.
Видно четкую связь доли золота в руде с долями серебра и свинца - чем выше доля золота, тем выше и доля этих металлов. Доля золота и серебра в руде, поступающей на данное предприятие, в среднем около 8% (максимально - около 14%), свинца меньше - около 3.5% (максимально около 7%). Количество зольных компонентов может доходить до 50%, но иногда минимально, около 0.
Посмотрим, как меняется концентрация металлов (Au, Ag, Pb) и зольных компонентов после флотации и двух стадий очитски.
# distribution histograms
fig, axs = plt.subplots(2, 2, figsize=(7, 7))
fig.suptitle("Распределение долей компонентов на каждой стадии", fontsize="x-large")
sns.histplot(data=data_full, x='rougher.input.feed_au', kde=True, color="skyblue", ax=axs[0, 0])
sns.histplot(data=data_full, x='rougher.output.concentrate_au', kde=True, color="green", ax=axs[0, 0])
sns.histplot(data=data_full, x='primary_cleaner.output.concentrate_au', kde=True, color="salmon", ax=axs[0, 0])
sns.histplot(data=data_full, x='final.output.concentrate_au', kde=True, color="gold", ax=axs[0, 0]).set(
title='Золото', xlabel='%', ylabel='Количество партий')
sns.histplot(data=data_full, x='rougher.input.feed_ag', kde=True, color="skyblue", ax=axs[0, 1])
sns.histplot(data=data_full, x='rougher.output.concentrate_ag', kde=True, color="green", ax=axs[0, 1])
sns.histplot(data=data_full, x='primary_cleaner.output.concentrate_ag', kde=True, color="salmon", ax=axs[0, 1])
sns.histplot(data=data_full, x='final.output.concentrate_ag', kde=True, color="gold", ax=axs[0, 1]).set(
title='Серебро', xlabel='%', ylabel='Количество партий')
sns.histplot(data=data_full, x='rougher.input.feed_pb', kde=True, color="skyblue", ax=axs[1, 0])
sns.histplot(data=data_full, x='rougher.output.concentrate_pb', kde=True, color="green", ax=axs[1, 0])
sns.histplot(data=data_full, x='primary_cleaner.output.concentrate_pb', kde=True, color="salmon", ax=axs[1, 0])
sns.histplot(data=data_full, x='final.output.concentrate_pb', kde=True, color="gold", ax=axs[1, 0]).set(
title='Свинец', xlabel='%', ylabel='Количество партий')
sns.histplot(data=data_full, x='rougher.input.feed_sol', kde=True, color="skyblue", ax=axs[1, 1])
sns.histplot(data=data_full, x='rougher.output.concentrate_sol', kde=True, color="green", ax=axs[1, 1])
sns.histplot(data=data_full, x='primary_cleaner.output.concentrate_sol', kde=True, color="salmon", ax=axs[1, 1])
sns.histplot(data=data_full, x='final.output.concentrate_sol', kde=True, color="gold", ax=axs[1, 1]).set(
title='Зольные компоненты', xlabel='%', ylabel='Количество партий')
plt.tight_layout()
plt.legend(labels=["Руда",
"Черновой концентрат",
"Первичная очистка",
"Финальный концентрат"],
bbox_to_anchor=(1.01, 1), loc='upper left', borderaxespad=0)
plt.show()
Посмотрим на изменение суммарной концентрации всех веществ на разных стадиях: в сырье, в черновом и финальном концентратах.
# distribution histograms
sns.histplot(data=data_full,
x=data_full[['rougher.input.feed_au',
'rougher.input.feed_ag',
'rougher.input.feed_pb',
'rougher.input.feed_sol']].sum(axis=1),
kde=True, color="skyblue")
sns.histplot(data=data_full,
x=data_full[['rougher.output.concentrate_au',
'rougher.output.concentrate_ag',
'rougher.output.concentrate_pb',
'rougher.output.concentrate_sol']].sum(axis=1),
kde=True, color="green")
sns.histplot(data=data_full,
x=data_full[['primary_cleaner.output.concentrate_au',
'primary_cleaner.output.concentrate_ag',
'primary_cleaner.output.concentrate_pb',
'primary_cleaner.output.concentrate_sol']].sum(axis=1),
kde=True, color="salmon")
sns.histplot(data=data_full,
x=data_full[['final.output.concentrate_au',
'final.output.concentrate_ag',
'final.output.concentrate_pb',
'final.output.concentrate_sol']].sum(axis=1),
kde=True, color="gold").set(title='Распределение сумм долей компонентов',
xlabel='%',
ylabel='Количество партий')
plt.legend(labels=["Руда",
"Черновой концентрат",
"Первичная очистка",
"Финальный концентрат"])
plt.show()
Вывод: Видно, что в процессе обогащения концентрация золота увеличивается: в среднем около 10% в руде, около 20% в черновом концентрате, около 30% после первой очистки и более 40% в финальном продукте. Для свинца наблюдается похожая динамика, за исключением того, что вторая очистка уже не приводит к увеличению концентрации. Для серебра картина несколько иная - флотация увеличивает его концентрацию в черновом концентрате, однако последующие очистки снижают его количество в концентратах. Зольные компоненты уменьшаются в доле на каждом этапе технологического процесса, что может говорить о том, что как раз от них и стараются избавиться.
Как видно из гистограмм распределения концентраций металлов и как мы видели в ранее в анализе - в целевых переменных - коэффициентах обогащения - есть аномальные значения, равные 0 и 100. Нулевые значения связанны с нулевой концентрацией золота в черновом и в финальном концентратах соответсвенно. 100% извлечение золота на финальном этапе связано с нулевыми значениями его концентрации в отвальных хвостах. Причина аномалий - скорее всего какие-то технологические ошибки.
Посмотрим, какой процент составляют аномальные значения в тестовой и обучающей выборках.
anom_train=len(data_train[(data_train["rougher.output.recovery"] < 0.001) |
(data_train["rougher.output.recovery"] > 99.99) |
(data_train["final.output.recovery"] < 0.001) |
(data_train["final.output.recovery"] > 99.99)])/len(data_train)
anom_test=len(data_test[(data_test["rougher.output.recovery"] < 0.001) |
(data_test["rougher.output.recovery"] > 99.99) |
(data_test["final.output.recovery"] < 0.001) |
(data_test["final.output.recovery"] > 99.99)])/len(data_test)
print('Процент аномальных значений коэффициентов обогащения:')
print(f'Обучающая выборка {anom_train:.2%}')
print(f'Тестовая выборка {anom_test:.2%}')
Процент аномальных значений коэффициентов обогащения: Обучающая выборка 3.02% Тестовая выборка 2.87%
Аномальные значения составляют около 3% как в обучающей, так и в тестовой выборках. Поскольку мы не можем заменить значения в целевых переменных - удалим их из обучающей выборки.
# drop 0 and 100 from the training data
data_train = data_train[(
(data_train["rougher.output.recovery"] > 0.001) & (data_train["rougher.output.recovery"] < 99.99)) & (
(data_train["final.output.recovery"] > 0.001) & (data_train["final.output.recovery"] < 99.99))]
print('Нулевые или =100% коэффициенты обогащения в обучающей выборке:')
print(len(data_train[(data_train["rougher.output.recovery"] < 0.001) |
(data_train["rougher.output.recovery"] > 99.99) |
(data_train["final.output.recovery"] < 0.001) |
(data_train["final.output.recovery"] > 99.99)]))
Нулевые или =100% коэффициенты обогащения в обучающей выборке: 0
В данных имелись пропущенные значения, для построения модели их необходимо обработать.
# number of NaN
print(f'Количество пропущенных значений в train (N={len(data_train)})')
print(data_train.isna().sum()[data_train.isna().sum() > 0]
.sort_values(ascending=False), '\n')
print(f'Количество пропущенных значений в test (N={len(data_test)})')
print(data_test.isna().sum()[data_test.isna().sum() > 0]
.sort_values(ascending=False))
Количество пропущенных значений в train (N=13721) rougher.input.floatbank11_xanthate 374 rougher.state.floatbank10_e_air 368 secondary_cleaner.state.floatbank2_a_air 211 rougher.input.feed_size 139 rougher.input.feed_pb 100 primary_cleaner.input.xanthate 87 rougher.input.feed_sol 58 rougher.input.floatbank11_sulfate 29 rougher.input.floatbank10_sulfate 19 primary_cleaner.input.depressant 15 rougher.input.feed_rate 8 secondary_cleaner.state.floatbank2_b_air 7 primary_cleaner.input.sulfate 7 secondary_cleaner.state.floatbank3_a_air 4 secondary_cleaner.state.floatbank4_a_air 4 rougher.input.floatbank10_xanthate 3 primary_cleaner.state.floatbank8_d_air 3 primary_cleaner.state.floatbank8_a_air 2 primary_cleaner.state.floatbank8_c_air 2 primary_cleaner.state.floatbank8_b_air 2 secondary_cleaner.state.floatbank3_b_air 1 secondary_cleaner.state.floatbank3_b_level 1 secondary_cleaner.state.floatbank6_a_air 1 secondary_cleaner.state.floatbank5_a_level 1 secondary_cleaner.state.floatbank4_a_level 1 secondary_cleaner.state.floatbank4_b_air 1 secondary_cleaner.state.floatbank4_b_level 1 secondary_cleaner.state.floatbank5_a_air 1 secondary_cleaner.state.floatbank5_b_air 1 secondary_cleaner.state.floatbank3_a_level 1 secondary_cleaner.state.floatbank5_b_level 1 rougher.state.floatbank10_b_level 1 secondary_cleaner.state.floatbank2_b_level 1 secondary_cleaner.state.floatbank2_a_level 1 rougher.state.floatbank10_c_level 1 rougher.state.floatbank10_c_air 1 rougher.state.floatbank10_b_air 1 rougher.state.floatbank10_a_level 1 rougher.state.floatbank10_a_air 1 primary_cleaner.state.floatbank8_d_level 1 primary_cleaner.state.floatbank8_c_level 1 primary_cleaner.state.floatbank8_b_level 1 primary_cleaner.state.floatbank8_a_level 1 secondary_cleaner.state.floatbank6_a_level 1 dtype: int64 Количество пропущенных значений в test (N=5290) rougher.input.floatbank11_xanthate 25 rougher.input.feed_sol 21 secondary_cleaner.state.floatbank3_a_air 9 rougher.input.floatbank11_sulfate 8 primary_cleaner.input.depressant 5 rougher.input.floatbank10_sulfate 5 primary_cleaner.input.sulfate 4 primary_cleaner.input.xanthate 4 rougher.input.feed_rate 3 secondary_cleaner.state.floatbank2_a_air 3 secondary_cleaner.state.floatbank2_b_air 2 rougher.input.feed_size 1 dtype: int64
Посмотрим, как были распределены пропуски некоторых признаков во времени на полных данных.
# distribution of NaNs in time
ax = data_full.plot(x='date',
y='rougher.input.feed_au',
kind='scatter', c='gray', alpha=0.2,
figsize=(15,5), label='not NAN')
data_full[data_full['rougher.input.feed_size'].isna()].plot(
x='date', y='rougher.input.feed_au', kind='scatter', c='r',
ax=ax, label='NAN, rougher.input.feed_size')
data_full[data_full['rougher.input.feed_pb'].isna()].plot(
x='date', y='rougher.input.feed_au', kind='scatter', c='c',
ax=ax, label='NAN, rougher.input.feed_pb')
data_full[data_full['rougher.input.feed_sol'].isna()].plot(
x='date', y='rougher.input.feed_au', kind='scatter', c='b',
ax=ax, label='NAN, rougher.input.feed_sol')
plt.xlabel('Дата')
plt.ylabel('Доля золота в руде, %')
plt.legend(title='Пропущенные значения')
plt.title('Распределение пропущенных значений в некоторых признаках')
plt.show()
Видно, что для некоторых переменных значения пропущены "кластерами" - вероятно в следствие ошибок в измерениях. Отсутсвие же измерений размера поступающих во флотационную установку гранул сырья распределено равномерно по данным, что может говорить о том, что иногда его, вероятно, затруднительно определить (маленькие гранулы?).
Поскольку отсутвующие данные распределены по датасету или сгруппированы в одних диапазонах значений - заполним их соседними значениями, тем более, что в техническом задании было указано, что соседние показатели обычно схожи.
# fill NAN in all dataset
data_full = data_full.fillna(method='ffill')
print('Количество пропусков в полном датасете:',
data_full.isna().sum()[data_full.isna().sum() > 0])
Количество пропусков в полном датасете: Series([], dtype: int64)
Заполним пропуски в тестовых и обучающих данных значениями из полного датасета.
# fill NAN in training and test data
data_train = (data_train
.set_index('date')
.fillna(data_full.set_index('date')))
data_test = (data_test
.set_index('date')
.fillna(data_full.set_index('date')))
print('Количество пропусков в обучающих данных:',
data_train.isna().sum()[data_train.isna().sum() > 0])
print('Количество пропусков в тестовых данных:',
data_test.isna().sum()[data_test.isna().sum() > 0])
Количество пропусков в обучающих данных: Series([], dtype: int64) Количество пропусков в тестовых данных: Series([], dtype: int64)
Для прогнозирования коэффициентов обогащения проверим две модели - линейную регрессию и случайный лес. Будем проверять модели отдельно для прогнозирования коэффициентов обогощения чернового и финального концентратов.
В качестве метрики качества моделей будем использовать симметричное среднее абсолютное процентное отклонение, sMAPE, одинаково учитывающее масштаб и целевого признака, и предсказания.
Напишем функции для вычисления sMAPE и итогового sMAPE, обобщающего качество модели для предсказания коэффициентов обогащения чернового и финального концентратов.
# define function to calculate Symmetric Mean Absolute Percentage Error (sMAPE)
def smape_score(y_true, y_pred):
y_true = np.array(y_true)
res = np.mean(
np.abs(y_true - y_pred) / ((np.abs(y_true) + np.abs(y_pred))*0.5)
)*100
return res
# define function to calculate final sMAPE
def final_smape(smape_rougher, smape_final):
return (smape_rougher*0.25 + smape_final*0.75)
Подготовка данных для моделей
Основываясь на проведенном анализе признаков, для построения модели исключим:
rougher.input.feed_ag, так как он практически "повторяет" rougher.input.feed_aurougher.input.floatbank10_xanthate, так как он коррелирует с rougher.input.floatbank10_sulfate, а последний как кажется, имеет большую связь с целевым признаком.rougher.input.floatbank11, так как они практически "повторяют" rougher.input.floatbank10rougher.state.floatbank10_a, c, d, e, f, так как они практически "повторяют" rougher.state.floatbank10_b# training data for "Rougher recovery" model
data_train_rougher = data_train[['rougher.input.feed_pb',
'rougher.input.feed_rate',
'rougher.input.feed_size',
'rougher.input.feed_sol',
'rougher.input.feed_au',
'rougher.input.floatbank10_sulfate',
'rougher.state.floatbank10_b_air',
'rougher.state.floatbank10_b_level',
'rougher.output.recovery']]
data_train_rougher.shape
(13721, 9)
# test data for "Rougher recovery" model
data_test_rougher = data_test[list(data_train_rougher)]
data_test_rougher.shape
(5290, 9)
# targets and features
x_train_rougher = data_train_rougher.drop('rougher.output.recovery', axis=1)
y_train_rougher = data_train_rougher['rougher.output.recovery']
x_test_rougher = data_test_rougher.drop('rougher.output.recovery', axis=1)
y_test_rougher = data_test_rougher['rougher.output.recovery']
# Create the model
model_lr = LinearRegression()
# Cross-validation
scores_lr = cross_val_score(model_lr, x_train_rougher, y_train_rougher, cv=5,
scoring=make_scorer(smape_score))
score_lr = scores_lr.mean()
print(f'Среднee sMAPE: {score_lr:.2f} со стандартным отклонением {scores_lr.std():.2f}')
Среднee sMAPE: 6.73 со стандартным отклонением 1.73
# Create the model
model_rf = RandomForestRegressor(random_state=123)
# Hyperparameters to check
params = {'max_depth': range(1, 30), 'n_estimators': range(10, 200, 10)}
# Cross-validation
grid_model_rougher = RandomizedSearchCV(model_rf, params,
n_jobs=-1,
random_state=123, cv=5,
scoring=make_scorer(smape_score, greater_is_better=False))
# Fit the model on the training data
grid_model_rougher.fit(x_train_rougher, y_train_rougher)
print(f'Гиперпараметры лучшей модели: {grid_model_rougher.best_params_}')
print(f'sMAPE: {abs(grid_model_rougher.best_score_):.2f}')
Гиперпараметры лучшей модели: {'n_estimators': 190, 'max_depth': 8}
sMAPE: 6.54
# Create the dummy model
dummy_regr = DummyRegressor(strategy="mean")
# Cross-validation
scores_dr = cross_val_score(dummy_regr, x_train_rougher, y_train_rougher, cv=5,
scoring=make_scorer(smape_score, greater_is_better=False))
score_dr = scores_dr.mean()
print(f'sMAPE случайной модели: {abs(score_dr):.2f} со стандартным отклонением {scores_dr.std():.2f}')
sMAPE случайной модели: 7.80 со стандартным отклонением 1.70
Вывод: Случайный лес для регрессии из 190 деревьев глубиной 8 показал самую маленькую ошибку, она почти на 1.5% меньше, чем у случайной модели.
Подготовка данных для моделей
Основываясь на проведенном анализе признаков, для построения модели возьмем признаки из первой модели, кроме самого "неважного" - rougher.input.feed_rate, а также не будем брать физические параметры флотации - уровень жидкости и объем воздуха, их возьмем из второго этапа очистки.
Кроме этого, из этапов очистки добавим primary_cleaner.input.xanthate, primary_cleaner.input.sulfate, физические параметры secondary_cleaner.state.floatbank3_b_air, level.
Не будем также включать: primary_cleaner.input.feed_size, так как размеры достаточно однородные и не видно их влияния, primary_cleaner.input.depressant, так как его влияния не видно.
# training data for "Final recovery" model
data_train_final = data_train[['primary_cleaner.input.sulfate',
'primary_cleaner.input.xanthate',
'rougher.input.feed_pb',
'rougher.input.feed_size',
'rougher.input.feed_sol',
'rougher.input.feed_au',
'rougher.input.floatbank10_sulfate',
'secondary_cleaner.state.floatbank3_b_air',
'secondary_cleaner.state.floatbank3_b_level',
'final.output.recovery']]
data_train_final.shape
(13721, 10)
# test data for "Final recovery" model
data_test_final = data_test[list(data_train_final)]
data_test_final.shape
(5290, 10)
# targets and features
x_train_final = data_train_final.drop('final.output.recovery', axis=1)
y_train_final = data_train_final['final.output.recovery']
x_test_final = data_test_final.drop('final.output.recovery', axis=1)
y_test_final = data_test_final['final.output.recovery']
# Create the model
model_lr = LinearRegression()
# Cross-validation
scores_lr = cross_val_score(model_lr, x_train_final, y_train_final, cv=5,
scoring=make_scorer(smape_score, greater_is_better=False))
score_lr = scores_lr.mean()
print(f'Средняя оценка качества модели: {abs(score_lr):.2f} со стандартным отклонением {scores_lr.std():.2f}')
Средняя оценка качества модели: 9.46 со стандартным отклонением 1.51
# Create the model
model_rf = RandomForestRegressor(random_state=123)
# Hyperparameters to check
params = {'max_depth': range(1, 30), 'n_estimators': range(10, 200, 10)}
# Cross-validation
grid_model = RandomizedSearchCV(model_rf, params, n_jobs=-1, random_state=123, cv=5,
scoring=make_scorer(smape_score, greater_is_better=False))
# Fit the model on the training data
grid_model.fit(x_train_final, y_train_final)
print(f'Гиперпараметры лучшей модели: {grid_model.best_params_}')
print(f'sMAPE: {abs(grid_model.best_score_):.2f}')
Гиперпараметры лучшей модели: {'n_estimators': 70, 'max_depth': 5}
sMAPE: 9.95
# Create the dummy model
dummy_regr = DummyRegressor(strategy="mean")
# Cross-validation
scores_dr = cross_val_score(dummy_regr, x_train_final, y_train_final, cv=5,
scoring=make_scorer(smape_score, greater_is_better=False))
score_dr = scores_dr.mean()
print(f'sMAPE случайной модели: {abs(score_dr):.2f} со стандартным отклонением {scores_dr.std():.2f}')
sMAPE случайной модели: 10.30 со стандартным отклонением 0.94
Вывод: Самую маленькую ошибку показала модель Линейной регрессии, sMAPE=9.46, что почти на 1% меньше, чем у случайной модели.
# Create the model
model_rougher = RandomForestRegressor(max_depth=8, n_estimators=190, random_state=12345)
# Fit the model on the training data
model_rougher.fit(x_train_rougher, y_train_rougher)
RandomForestRegressor(max_depth=8, n_estimators=190, random_state=12345)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
RandomForestRegressor(max_depth=8, n_estimators=190, random_state=12345)
# Make predictions on the test data
pred_test_rougher = model_rougher.predict(x_test_rougher)
# Create the dummy model
dummy_regr = DummyRegressor(strategy="mean")
# Fit the model on the training data
dummy_regr.fit(x_train_rougher, y_train_rougher)
# Make predictions on the test data
pred_dummy_rougher = dummy_regr.predict(x_test_rougher)
# Evaluate the model
smape_model_rougher = smape_score(y_test_rougher, pred_test_rougher)
smape_dummy_rougher = smape_score(y_test_rougher, pred_dummy_rougher)
print('sMAPE:', round(smape_model_rougher, 4))
print('sMAPE случайной модели:', round(smape_dummy_rougher, 4))
sMAPE: 8.1025 sMAPE случайной модели: 9.0755
Посмотрим на то, какие признаки были важными для принятия решения моделью:
# Importance of the features for RandomForest
feature_importances = pd.DataFrame(
{'features': list(x_train_rougher.columns),
'feature_importance': model_rougher.feature_importances_})
# plot feature importances
feature_importances.sort_values(by='feature_importance', ascending=False).plot(kind='bar', x='features')
plt.ylabel('Feature_importance')
plt.xlabel('')
Text(0.5, 0, '')
Вывод: Качество модели, проверенное на тестовой выборке получилось выше, чем у случайной модели. На основании данной модели можно предсказывать значения коэффициентов обогащения чернового концентрата, ошибаясь лишь в 8% случаев. Самым важным признаком для предсказания является содержание золота в руде, что логично. Важен также размер гранул сырья, а вот скорость их подачи большой роли не играет.
# Create the model
model_final = LinearRegression()
# Fit the model on the training data
model_final.fit(x_train_final, y_train_final)
LinearRegression()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
LinearRegression()
# Make predictions on the test data
pred_test_final = model_final.predict(x_test_final)
# Create the dummy model
dummy_regr = DummyRegressor(strategy="mean")
# Fit the model on the training data
dummy_regr.fit(x_train_final, y_train_final)
# Make predictions on the test data
pred_dummy_final = dummy_regr.predict(x_test_final)
# Evaluate the model
smape_model_final = smape_score(y_test_final, pred_test_final)
smape_dummy_final = smape_score(y_test_final, pred_dummy_final)
print('sMAPE:', round(smape_model_final, 4))
print('sMAPE случайной модели:', round(smape_dummy_final, 4))
sMAPE: 9.4904 sMAPE случайной модели: 10.1791
Вывод: Качество модели, проверенное на тестовой выборке получилось почти на 1% выше, чем у случайной модели. На основании данной модели можно предсказывать финальные значения коэффициентов обогащения, ошибаясь лишь в 9,5% случаев.
Рассчитаем итоговую оценку качества моделей.
f'Итоговая sMAPE: {final_smape(smape_model_rougher, smape_model_final):.2f}'
'Итоговая sMAPE: 9.14'
Из данных видно, что руды, используемые на данном предприятии, являются комплексными - в них содержится поровну золота и серебра, а также свинец, причем их соотношение как правило линейно зависимо - чем больше золота в руде, тем больше и серебра и свинца. Содержание золота не очень высокое - 8%, но из более бедных руд иногда удается извлечь больше золота. Это указывает не только на то, что руды отличаются между собой, но и на то, что стоит обращать внимание на процесс обогащения и его параметры, возможно, они также могут значимо влиять на коэффициенты обогащения. Например, более бедные руды также может быть выгодно использовать - некоторые из них могут иметь высокий коэффициент обогащения с использованием низкого количества флотационного реагента сульфида натрия, что может снижать затраты обогащения.
С каждой стадией технологического процесса доля золота "на выходе" повышается примерно на 10%, для других металлов такой четкой зависимости нет, что говорит о том, что процесс оптимизирован под обогащение золота. Возможно, стоит дополнительно отдельно проанализировать его содержание в отвальных хвостах и связь этого параметра с другими.
Коэффициент обогащения чернового концентрата как правило составляет 80-90%, а финального концентрата чуть ниже - 60-70%. Из анализа данных видно, что больше всего на коэффициент обогащения чернового концентрата влияет доля золота и других металлов в руде, некоторое влияние имеют и размер гранул сырья, количество флотационных реагентов. На финальный коэффициент обогащения также влияет концентрация металлов в руде, но в меньшей степени, плюс, содержание флотационных реагентов в черновом концентрате перед очисткой.
В данных есть пропущенные и аномальные значения. Так, концентрация золота на "выходе" технологического этапа или в отвальных хвостах могла равняться 0. Проанализировав такие случаи кажется, что это связано с какими-то технологическими ошибками, а не особенностями сырья. Для обучения модели пропущенные значения были заменены на ближайшие соседние, а аномальные в обучающей выборке - удалены.
Анализ данных позволил разработать модели для предсказания значений коэффициентов обогащения в черновом и финальном концентратах. Итоговая оценка качества моделей составляет около 9%, то есть используя такой прогноз мы будем ошибаться примерно в 9% случаев. Разработка модели машинного обучения для предсказания коэффициента восстановления золота из золотосодержащей руды поможет оценивать перспективность руды и оптимизировать параметры ее обогащения для более эффективного производства.